[英]Simultaneous read write on value object of ConcurrentHashMap
我有一個ConcurrentHashMap:
ConcurrentHashMap<ID,Object> map;
在我的應用程序中,此映射為高讀和低寫
閱讀的工作方式如下:
public Response getObject() {
Response response = createResponse();
Object obj = map.get(ID);
if (obj != null) {
if (obj.getAttribute1() == some_value) {
response.setAttr1(obj.getAttr1());
response.setAttr2(obj.getAttr2());
}
}
return response;
}
更新的工作方式如下:
public void updateObject(Object obj, int action) {
if (action == ADD) {
map.put(obj.getID(), obj);
} else if (action == UPDATE) {
object oldObj = map.get(obj.getID());
if (oldObj != null) {
map.put(obj.getID(), obj);
}
} else if (action == REMOVE) {
object oldObj = map.get(obj.getID());
if (oldObj != null) {
map.remove(obj.getID());
}
}
}
現在我的問題是,ConcurrentHashMap是否足以在多線程環境中以線程安全的方式工作,還是必須通過ReadWrite鎖從外部鎖定Object或使用Object的克隆?
假設在從地圖讀取obj的情況下,ConcurrentHashMap將確保它將返回最新的寫入對象,但是當在讀取后立即由編寫器線程刪除/更新該對象時該怎么辦。Read對象(已從地圖刪除/更新)用於准備響應對象,其屬性用於做出某些決定。
而更新地圖的更好方法應該是什么?
為了使代碼相對於ConcurrentHashMap
而言是線程安全的,您應該使用相應的compute
方法(原子地執行):
public Response getObject() {
Response response = createResponse();
map.computeIfPresent(ID, (k, v) -> {
if (v == some_value) {
response.setAttr1(v.getAttr1());
response.setAttr2(v.getAttr2());
}
return v;
}
return response;
}
和:
public void updateObject(Object obj, int action) {
if (action == ADD) {
map.put(obj.getID(), obj);
} else if (action == UPDATE) {
map.computeIfPresent(obj.getID(), (k, v) -> obj);
} else if (action == REMOVE) {
map.remove(obj.getID());
}
}
如果只有一個編寫器,那么這是線程安全的。 否則,您執行的操作之間會出現競爭狀態。 因此,有些操作可以自動執行這些操作並簡化代碼。
public void updateObject(Object obj, int action) {
switch (action) {
case ADD:
map.put(obj.getID(), obj);
break;
case UPDATE:
map.computeIfPresent(obj.getID(), (k, v) -> obj);
break;
case REMOVE:
map.remove(obj.getID());
break;
}
}
最有可能的是,您不需要特殊的更新操作,也可以將其put
我強烈建議不要將Object
用作自定義類,而應使用新名稱。
讀取后立即由編寫器線程刪除/更新該對象該怎么辦
如果刪除該對象,則對持有該引用的另一個線程沒有影響。 如果通過在地圖中放置新對象來更新對象,則可以,但是,如果更新添加的對象,則可能不是線程安全的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.