2012-09-26 51 views
3

我正在嘗試使用GCD作爲幾十個原子屬性的替代品。我記得在WWDC上他們在談論GCD可以用於高效的事務鎖定機制。如何使用GCD輕量級事務鎖定資源?

在我的OpenGL ES runloop方法,我把所有的繪圖代碼由dispatch_sync上的自定義顯示串行隊列執行的塊。 runloop被一個CADisplayLink調用,這是我在主線程中發生的知識。

有實例變量,並且都繪製而且還有控制什麼會被吸引使用的屬性。問題是必須有一些鎖定來防止併發問題,以及在兩個繪製幀之間的主線程中事務性地查詢和修改OpenGL ES場景的狀態。

我可以通過在該序列隊列執行塊修改一組屬性,以事務的方式與GCD。

但似乎我不能讀取值到主線程,使用GCD,同時阻塞執行繪圖代碼的隊列。 dispatch_synch沒有返回值,但我想要訪問演示文稿值之間的繪製兩個框架的讀取和寫入。

難道這barrier件事,他們都在談論什麼?這是如何運作的?

+0

您可能會發現原子屬性的工作方式也一樣,並且您不需要重構代碼。 –

回答

5

這是異步編寫器/同步閱讀器模型的設計目的。比方說,你有伊娃(和討論的目的,讓我們假設你已經走了一丁點進一步和封裝所有的高德成單一結構,只是爲了簡單起見:

struct { 
    int x, y; 
    char *n; 
    dispatch_queue_t _internalQueue; 
} myIvars; 

讓我們進一步假設(對簡潔),你已經在dispatch_once(先前在代碼初始化實例變量),並創建了_internalQueue作爲串行隊列dispatch_queue_create()

現在,寫一個值:

dispatch_async(myIvars._internalQueue, ^{ myIvars.x = 10; }); 
dispatch_async(myIvars._internalQueue, ^{ myIvars.n = "Hi there"; }); 

而且讀一個:

__block int val; __block char *v; 
dispatch_sync(myIvars._internalQueue, ^{ val = myIvars.x; }); 
dispatch_sync(myIvars._internalQueue, ^{ v = myIvars.n; }) 

使用內部隊列確保一切適當的系列化和寫入可以異步發生,但是讀取等待所有未決寫給你回值之前完成。許多「GCD意識」數據結構(或具有內部數據結構的例程)將串行隊列作爲實現細節用於此目的。

1

dispatch_sync允許您指定第二個參數爲完成塊的,你可以從你的串行隊列獲取值,並利用它們在你的主thread.So它會看起來像

dispatch_sync(serialQueue,^{ 
    //execute a block 
    dispatch_async(get_dispatch_main_queue,^{ 

     //use your calculations here 
    }); 
}); 

和串行隊列處理併發部分本身。因此,如果另一塊試圖同時訪問相同的代碼,它將由隊列本身處理。希望這沒有什麼幫助。

+0

我看不到代碼示例中的第二個參數。它應該是dispatch_sync塊內的dispatch_async *還是dispatch_sync的參數?另外,如果您調用dispatch_async:在初始dispatch_sync返回後,第二個塊中寫回的更改還沒有,因爲它是異步的。或者我錯過了這一點? –

+0

對第二個參數部分抱歉...我的意思是dispatch_async/dispatch_sync ...我沒有得到「在第二個塊中寫回的更改還沒有,因爲它是異步的」?你運行的dispatch_sync塊將確保你有下一個異步塊的值。但正如我所說的第二個塊是完成塊它可以是異步或同步...通常我使用異步,因爲它提供了更好的用戶體驗或者如果代碼駐留在我的任何初始例程中,則進行同步。 –