Java字节数组多线程

时间:2012-11-20 09:14:14

标签: java multithreading concurrency thread-safety race-condition

如果我有多个线程访问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();
}

4 个答案:

答案 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(),则有可能在多线程环境中使用新值覆盖现有值。