如果我有多个线程访问getter和setter,这个代码是否会遇到任何竞争条件?我不介意getter在set操作期间获取旧数据,但只要它不会导致异常或者为null。
ConcurrentHashMap<String, Object> hashMap =
new ConcurrentHashMap<String, Object> ();
void setByteArray(String string, byte[] byteArray) {
hashMap.put(string, byteArray.clone());
}
byte[] getByteArray(String string) {
return ((byte[]) hashMap.get(string)).clone();
}
答案 0 :(得分:4)
这几乎线程安全(如果有这样的话)。唯一缺少的是声明hashMap
字段final
。这样可以保证地图的safe publication。
除此之外,我没有看到任何问题(关于线程安全)。 ConcurrentHashMap是线程安全的,因此存储和检索字节数组也应该是。
此外,由于您始终复制字节数组,因此除了存储在Map中的字符串之外,它们永远不会在线程之间共享。 ConcurrentHashMap
将安全地将它们发布到所有线程,因为它们永远不会被修改(意味着它们实际上是不可变的),所以线程安全性得到保证。
最后,根据评论,这里有一些关于其他方面的改进版本:
private final ConcurrentHashMap<String, Object> hashMap =
new ConcurrentHashMap<String, Object> ();
void setByteArray(String string, byte[] byteArray) {
hashMap.put(string, byteArray.clone());
}
byte[] getByteArray(String string) {
Object result = hashMap.get(string);
if(result == null)
return null;
else
return ((byte[]) result).clone();
}
第一件事是private
的{{1}}修饰符,因此子类不能存储任何其他对象,例如共享字节数组。
第二件事是在getter中进行空检查。您可能希望根据您的要求将hashMap
替换为return null;
或其他内容。
答案 1 :(得分:0)
ConcurrentHashMap
将会处理它,所以我的结论是你应该满足你的要求。
答案 2 :(得分:0)
似乎没问题,因为ConcurrentHashMap
处理线程安全问题,根据规范http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html
答案 3 :(得分:0)
您的代码不是线程安全的,不是因为字节内容,而是因为您使用ConcurrentHashMap的方式。
要在地图中添加项目,您应该在put()上使用putIfAbsent()。 PutIfAbsent()等同于
if (!map.containsKey(key)){
return map.put(key, value);
}
else {
return map.get(key);
}
(可能使用适当的同步块或关键字)
如果您只使用put(),则有可能在多线程环境中使用新值覆盖现有值。