2

我有一些需要同步的模型類。有一個Library類型的主要對象,其中包含多個Album對象(例如,想象一個音樂庫)。庫和專輯都通過執行NSCoding協議來支持序列化。我需要對庫的修改與兩個類的相冊修改和序列化進行同步,以便我知道這些更新不會影響彼此的腳趾,並且我不會在更新過程中對對象進行序列化。使用GCD的遞歸同步

我以爲我只是通過所有的對象共享調度隊列,dispatch_async所有的setter代碼和dispatch_sync的獲得者。這是簡單和容易的,但它不工作,因爲程序流程是遞歸的:

// In the Library class 
- (void) encodeWithCoder: (NSCoder*) encoder 
{ 
    dispatch_sync(queue, ^{ 
     [encoder encodeObject:albums forKey:…]; 
    }); 
} 

// In the Album class, same queue as above 
- (void) encodeWithCoder: (NSCoder*) encoder 
{ 
    dispatch_sync(queue, ^{ 
     [encoder encodeObject:items forKey:…]; 
    }); 
} 

現在序列化庫觸發專輯系列化,因爲這兩種方法在同一個隊列,代碼死鎖使用dispatch_sync。我已經看到這種模式:

- (void) runOnSynchronizationQueue: (dispatch_block_t) block 
{ 
    if (dispatch_get_current_queue() == queue) { 
     block(); 
    } else { 
     dispatch_sync(queue, block); 
    } 
} 

它是否有意義,它會工作,是否安全?有更簡單的方法來完成同步嗎?

回答

7

有關GCD中遞歸鎖的說明,請參閱遞歸鎖部分的dispatch_async man page。簡要總結一下,當發生這種情況時,重新考慮對象層次結構通常是一個好主意。

您也可以使用dispatch_set_target_queue()來控制執行層次(在較高級別的隊列中定位從屬隊列),一旦您重構了代碼,以便它是操作而不是需要控制的對象,但這也假設您無法簡單地使用完成回調來實現同樣的同步效果(坦率地說,由於抽象隊列層次結構難以概念化和調試,所以更推薦這樣做)。

我知道這並非真的是你要找的答案,但你對GCD的「你無法從那裏得到」的態度以及對如何做事情有更基本的反思「GCD方式「在這種情況下幾乎肯定是必要的。

+1

不是我希望聽到的答案,但一個很好的答案不過:)謝謝。 – zoul 2012-02-19 16:13:27