我有多個線程訪問的鍵值地圖:ConcurrentHashMap上的這種同步是否正確?
private final ConcurrentMap<Key, VersionValue> key_vval_map = new ConcurrentHashMap<Key, VersionValue>();
我定製get()
和put()
方法遵循典型的check-then-act
模式。因此,需要同步來確保原子性。爲了避免鎖定整個ConcurrentHashMap
,我定義:
private final Object[] locks = new Object[10];
{
for(int i = 0; i < locks.length; i++)
locks[i] = new Object();
}
而且get()
方法進入(它調用的ConcurrentHashMap
的get()
法):
public VersionValue get(Key key)
{
final int hash = key.hashCode() & 0x7FFFFFFF;
synchronized (locks[hash % locks.length]) // I am not sure whether this synchronization is necessary.
{
VersionValue vval = this.key_vval_map.get(key);
if (vval == null)
return VersionValue.RESERVED_VERSIONVALUE; // RESERVED_VERSIONVALUE is defined elsewhere
return vval;
}
}
的put()
方法去(它調用上述get()
方法):
public void put(Key key, VersionValue vval)
{
final int hash = key.hashCode() & 0x7FFFFFFF;
synchronized (locks[hash % locks.length]) // allowing concurrent writers
{
VersionValue current_vval = this.get(key); // call the get() method above
if (current_vval.compareTo(vval) < 0) // it is an newer VersionValue
this.key_vval_map.put(key, vval);
}
}
上述代碼有效。但是,正如你所知道的,在多線程編程中工作遠不是正確的。
我的問題是:
是必要的,正確的在我的代碼這種同步機制(尤其是
synchronized (locks[hash % locks.length])
)?
鎖實現提供了比 可以使用同步方法和語句可獲得的更廣泛的鎖定操作。
然後是可行的在我的代碼Lock
更換synchronization
?
編輯:如果您使用的是Java-8,請毫不猶豫地引用@nosid的答案。
'ConcurrentMap允許你使用樂觀鎖定而不是顯式同步':你可以給一些引用並且說一些關於'樂觀鎖定'的東西嗎?這超出了我的知識範圍。 – hengxin
我想我已經理解了''樂觀鎖定'的聰明想法'while(!replace(key,current_vval,new_vval));'。而'Striped'也是我想要的。謝謝。 – hengxin