2013-10-21 71 views
1

我有一個線程安全的類,一個取消令牌,從一個不穩定的可變狀態(未取消)轉換到一個穩定的不可變狀態(取消)。一旦一個實例變得不可變,我想在檢查狀態之前停止獲取鎖的成本。做一個原子讀取目標-C

這裏的是什麼東西像現在的簡化:

-(bool) isCancelled { 
    @synchronized(self) { 
     return _isCancelled; 
    } 
} 
-(bool) tryCancel { 
    @synchronized(self) { 
     if (_isCancelled) return false; 
     _isCancelled = true; 
    } 
    return true; 
} 

,我想什麼嘗試:

-(bool) isCancelled { 
    bool result; 
    // is the following correct? 
    // can the two full barriers be reduced to a single read-acquire barrier somehow? 
    OSMemoryBarrier(); 
    result = _isCancelled != 0; 
    OSMemoryBarrier(); 
    return result; 
} 
-(bool) tryCancel { 
    return OSAtomicCompareAndSwap32Barrier(0, 1, &_isCancelled); 
} 

使用兩個內存屏障正確的做法?我應該如何期望它與獲取鎖的成本(在此插入關於分析的標準不一致)?有沒有更便宜的方法來做到這一點?

+0

我已經刪除了我的答案,因爲你不明白。對於文檔中的內容,您應該知道還有其他函數,這些函數由Apple代碼調用。在從版本到版本的Apple中,喜歡更改他的代碼並聲明某些功能已被棄用,並且在下一版本中完全刪除它。這是現實,這是不是在文件中,但在現實生活中 – 2013-10-21 17:03:21

+0

@matheszabi蘋果公司不會貶低原子功能。這些不是UI函數,它們在每個版本中都獲得特性並略有改變,它們是無處不在的算法所使用的基本構建模塊。 –

回答

0

編輯:這聽起來像可能不成熟的優化。這是鎖定收購放慢東西嗎?

編輯2:其可能的編譯器優化將擊敗此。意識到。

如果您擔心雙重檢查鎖定問題,或許dispatch_once()可能對您有用?

會在這種情況下雙重檢查鎖定工作?

-(void) doSomething { 
    if (!_isCanceled) { //only attempt to acquire lock if not canceled already 
     @synchronized(self) { 
      if (!_isCanceled) // now check again (the double check part) 
       doSomethingElse(); 
     } 
    } 
} 

讀雙wikipedia entry檢查鎖定更多信息

+0

我無法衡量,如果我一開始就做不到,速度會更快。雙重鎖定鎖幾乎*在這裏工作,因爲你永遠不會看到一個撕裂的結果,你會最終收斂......但實際上該屬性總是檢查,看看是否有其他的事情已經完成,沒有獲得障礙你沒有得到必要的同步 - 與關係工作。 –

+0

@Strilanc你說一旦它被「取消」它不能被撤消,所以我不明白爲什麼你不能在鎖定獲取之前使用檢查(如果需要的話,再次後),以避免它被取消後鎖定。我唯一能想到的就是編譯優化,刪除檢查,但是IIRC現在可以在每個函數的基礎上關閉它。 –

+0

當有人有條件地使用僅在取消發生後纔可用的結果時,問題纔會顯現。因爲快樂案例沒有獲得收購障礙,所以他們最終可以在結果準備好之前看到令牌被取消。 –