2015-10-01 36 views
0

我擔心如果Guava Striped.get(key)方法是同步的。Guava Striped.get(key)是否同步?

那麼這個類線程安全嗎?

class UrlLocker { 
    Striped<Lock> locks = Striped.lazyWeakLock(1); 

    public void lock(Url url) { 
     locks.get(url).lock(); 
    } 

    public void unlock(Url url) { 
     locks.get(url).unlock(); 
    } 
} 

或者我需要同步我的方法來保護訪問鎖地圖嗎?

回答

0

潛入番石榴地圖製作工具實現,我發現魔法在com.google.common.collect.ComputingConcurrentHashMap.ComputingSegment#getOrCompu te方法中,它保護計算Lock並將其放入Map中的關鍵部分。

0

使之完全線程安全的,你就需要聲明locks實例作爲final

class UrlLocker { 
    final Striped<Lock> locks = Striped.lazyWeakLock(1); 

    public void lock(Url url) { 
     locks.get(url).lock(); 
    } 

    public void unlock(Url url) { 
     locks.get(url).unlock(); 
    } 
} 

而且,你的代碼的正確性取決於#hashcode實現Url類本身。如果你使用java.net.URL(它看起來不像你),如果DNS解析會在兩次調用之間改變,你會鬆動internet connection,hashcode將會改變。從Striped的javadoc

提取物:

...假設{@link對象#的hashCode()}正確的 鍵實現...

+0

你能否解釋爲什麼使鎖「最終」確保訪問鎖是線程安全的? –

+1

@GuillaumeDelafosse:分配給最終字段的_happens-before_關係可以從另一個線程訪問該字段。分配給非最終非易失性字段的情況並非如此。我認爲,至少在理論上,一個線程在創建後(在另一個線程上)立即調用UrlLocker方法可以看到未鎖定的「鎖」字段。無論如何,如果他們不需要改變,你應該總是讓場地最終成爲最終的。 – ColinD

+0

明白了。 無論如何,你確定locks.get是安全的。我的意思是,有沒有兩個線程調用它的機會不會讓Striped爲同一個鍵創建兩個Lock實例? 我試圖潛入Guava實現中,但在獲取和創建緩存中的鎖時沒有找到任何同步... –