【问题标题】:multiple threads using threadsafe collection使用线程安全集合的多线程
【发布时间】:2012-07-10 16:56:38
【问题描述】:

我不明白如何使下面的代码 sn-p 成为线程安全的。

class MapUser {
    Map<String,Integer> map = new ConcurrentHashMap<String,Integer>

    public void addToMap(String str, Integer val){
        if(checkMagicString(str)){
            map.put(str,val);
        }
    }

    private boolean checkMagicString(String str){
        //some logic to check Magic
        //this logic involved operation on the String parameter str i.e. subString,toCharArray etc
    }
}

注意 addToMap 方法被多个线程同时调用。我想确保维护线程安全。通过使用 ConcurrentHashMap,我可以确保线程安全地将值添加到其中。

但是我不明白 checkMagicString(String str) 方法如何保持线程安全?是让它同步的唯一方法吗?还是应该使调用方方法 addToMap 同步? 请注意,我没有在 checkMagicString 方法中访问地图。

【问题讨论】:

  • 我假设您正在访问map 内部的checkMagicString?如果没有,那么你很好。如果您是,请编辑您的帖子以显示这一点。

标签: java multithreading


【解决方案1】:

即使你将checkMagicString 设为原子,它也不会生成序列

if(checkMagicString(str)){
   map.put(str,val);
}

原子的,因为线程可以在if 检查和map.put 调用之间被中断,因此您最终可能会有两个线程插入相同的字符串。您需要锁定整个序列以确保安全。

编辑:如果上述行为是可接受的(即两个线程插入相同的键并覆盖值)并且checkMagicString 不在共享状态下运行,那么您的代码就可以正常工作。

【讨论】:

  • 这真的取决于 checkMagicString 在做什么。只要它不访问映射,这两个操作就不必是原子的以维护线程安全。
  • @assylias:这两个操作没有,但顺序应该是,因为我假设他不希望两个线程放置相同的字符串。
  • 你的意思是使用同步的addToMap方法吗?如果需要,那么多线程在这里有什么好处?
  • @Tudor 如果 checkMagicString 不访问地图,没有什么可以阻止 2 次连续调用将相同的字符串两次放入地图中。因此,使这 2 个操作原子化并没有什么不同(但会增加不必要的争用)。
  • @assylias:我同意,我是说不管checkMagicStrings 的原子性如何,生成的序列都不会是原子的。
【解决方案2】:

如果您想要的是原子操作,那么在这种情况下最好的办法是确保 checkMagicStr 是原子的,并在地图上使用原子操作:

boolean done = false;
while(!done) {
  Integer oldVal = map.get(str);
  if (checkMagicStr(str) {
    if (oldVal != null) {
      done = value == map.replace(str, val, oldVal); // otherwise try again...
    } else {
      done = null == map.putIfAbsent(str, val); // otherwise try again...
    }
  } else {
    done = true; // there's nothing to do...
  }
}

您可能希望对该 while 循环进行限制,并在它被命中时抛出异常,因为这可能会在高度并发的系统上永远运行。从你的问题中不清楚为什么这一切都是必要的,b/c 你所拥有的将是“线程安全的”,但也许这无论如何都会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 2014-09-06
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 2011-12-15
    相关资源
    最近更新 更多