經過許多小時的調試和分析後,我終於設法找出競爭條件的原因。解決它是另一回事!Java AWT drawImage競態條件 - 如何使用同步來避免它
爲了看到實際的競爭狀況,我在調試過程中錄製了一段視頻。我從那時起就進一步瞭解了這種情況,所以請原諒貧窮的評論和作爲調試過程一部分而實施的愚蠢機制。
http://screencast.com/t/aTAk1NOVanjR
所以,這種情況:我們有一個雙緩衝實現的表面(即java.awt.Frame中或窗口),其中有一個正在執行的線程,基本上連續循環,調用渲染進程(執行用戶界面佈局並將其渲染到後臺緩衝區),然後進行後期渲染,將渲染區域從後臺緩衝區傳送到屏幕。
這裏是雙重的僞代碼版本(完整版線Surface.java 824)緩衝呈現:
public RenderedRegions render() {
// pseudo code
RenderedRegions r = super.render();
if (r==null) // nothing rendered
return
for (region in r)
establish max bounds
blit(max bounds)
return r;
}
與任何AWT表面實現,它還實現(線507 AWT.java - 鏈接限制:( - 使用Surface.java鏈接,與高原/ AWT.java更換核心/ Surface.java)油漆/更新覆蓋這也從位塊傳輸的後備緩衝到屏幕上:
public void paint(Graphics gr) {
Rectangle r = gr.getClipBounds();
refreshFromBackbuffer(r.x - leftInset, r.y - topInset, r.width, r.height);
}
阻擊器實現(使用的drawImage線371 AWT.java)()函數:
/** synchronized as otherwise it is possible to blit before images have been rendered to the backbuffer */
public synchronized void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2) {
discoverInsets();
try {
window.getGraphics().drawImage(((AWTPixelBuffer)s).i,
dx + leftInset, dy + topInset, // destination topleft corner
dx2 + leftInset, dy2 + topInset, // destination bottomright corner
sx, sy, // source topleft corner
sx + (dx2 - dx), sy + (dy2 - dy), // source bottomright corner
null);
} catch (NullPointerException npe) { /* FIXME: handle this gracefully */ }
}
(警告:這是我開始變得清晰假設)
這裏的問題似乎是個drawImage是異步的一個!從refreshBackBuffer()通過繪製/更新blit首先被調用,但出現秒。
所以... blit已經同步。防止競爭狀況的顯而易見的方式不起作用。 :(
到目前爲止,我已經提出了兩個解決方案,但他們都不是理想的:在接下來的
重塊傳送渲染過程
缺點:性能損失,仍然得到了一點閃爍由於遇到競爭狀態(有效屏幕 - >無效屏幕 - >有效屏幕)時不要的blit油漆/更新,而不是設置刷新範圍,並使用這些邊界下一個渲染通道
缺點:讓黑當屏幕無效時閃爍主要應用程序線程正在追趕
這裏(1)似乎是兩個邪惡中較小的一個。 編輯:和(2)不起作用,獲得空白屏幕......(1)工作正常,但只是掩蓋了問題,可能仍然存在。
由於我對同步以及如何使用它的理解不夠,我似乎無法想象它是一種鎖定機制,它以某種方式說明了drawImage()的異步特性。
或者也許使用ImageObserver?
注意的是,由於應用程序的性質(Vexi,對於那些有興趣,網站是過時的,我只能用2個超鏈接)渲染線程必須是油漆/更新之外 - 它有一個單線程腳本模型和佈局過程(渲染的子流程)調用腳本。
我假設你的意思是'發生了什麼 - 問題仍然存在。我只是嘗試將blit代碼複製到paint方法中,並且其行爲相同。 (FWIW它並沒有真正的區別,因爲paint已經通過refreshFromBackBuffer間接地調用了blit,但爲了徹底,我嘗試了你的建議。) – 2011-02-10 01:50:24