6

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

4 回答 4

5

几乎是线程安全的(如果有的话)。唯一缺少的是声明hashMap字段final。这保证了地图的安全发布

除此之外,我没有看到任何问题(关于线程安全)。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修饰符 for hashMap,因此子类不能存储任何其他对象,例如共享字节数组。

第二件事是 getter 中的 null 检查。根据您的要求,您可能希望替换return null;为或其他内容。throw new IllegalArgumentException();

于 2012-11-20T09:20:21.907 回答
0

ConcurrentHashMap已准备好处理它,所以我的结论是,您应该可以满足您的要求。

于 2012-11-20T09:21:22.873 回答
0

It seems to be ok, as ConcurrentHashMap deals with thread safety, according to the spec http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html

于 2012-11-20T09:25:40.237 回答
0

Your code isn't threadsafe, not because of byte stuff but because of the way you use ConcurrentHashMap.

For adding items in the map, you should use putIfAbsent() over put(). PutIfAbsent() is equivalent to

   if (!map.containsKey(key)){
      return map.put(key, value);
   }
   else {
       return map.get(key);
   }

(probably with proper synchronized block or keyword)

If you just use put(), there are chance that you'll override existing value with new value in multi-thread environment.

于 2015-11-11T22:02:23.797 回答