下面的代码中会出现竞争条件吗

发布于 2024-11-17 03:57:01 字数 323 浏览 0 评论 0原文

从多个线程调用方法 addId 时是否会发生竞争?

private static Map<String , Long> table;

static {
    table = new ConcurrentHashMap<String  , Long>();
}

public static void addId(String key, Long value){

    if(table.containsKey(key)){
        table.remove(key);
    }

    table.put(key, value);
}

Could a race codition occur when invoking method addId from multiple threads ?

private static Map<String , Long> table;

static {
    table = new ConcurrentHashMap<String  , Long>();
}

public static void addId(String key, Long value){

    if(table.containsKey(key)){
        table.remove(key);
    }

    table.put(key, value);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

晚雾 2024-11-24 03:57:01

没有什么可以阻止另一个线程在 containsKey/removeput 之间放置一些值,因此在放置之前检查表是否已包含键是不可行的并不真正“安全”(或者更确切地说,并不真正“有意义”)。

为什么不直接执行

public static void addId(String key, Long value){
    table.put(key, value);
}

put 无论如何都会覆盖之前的任何条目。


如果您不希望多个线程同时执行该方法,请将该方法声明为synchronized

Nothing prevents another thread from putting some value between the containsKey/remove and the put, so checking if the table already contains a key before putting isn't really "safe" (or rather, doesn't really "make sense").

Why don't you just do

public static void addId(String key, Long value){
    table.put(key, value);
}

put will override any previous entry anyway.


If you don't want multiple threads to execute the method concurrently, declare the method as synchronized.

心碎无痕… 2024-11-24 03:57:01

是的,可能会发生竞争条件。

   if(table.containsKey(key)){
        table.remove(key);
    }

    table.put(key, value);

另一个线程可以修改 containsKey、删除和放置之间的表。不过,在执行 put() 之前不需要调用remove() - 删除 containsKey/remove 并且它将是线程安全的。

Yes, a race condition could occur.

   if(table.containsKey(key)){
        table.remove(key);
    }

    table.put(key, value);

Another thread could modify the table between your containsKey, the remove and the put. There's no need to call remove() before doing the put(), though - remove the containsKey / remove and it will be thread safe.

傻比既视感 2024-11-24 03:57:01

是的。

(看来我的答案必须是 30 个字符或更多)

addId 调用可能会产生竞争条件:一个线程可以尝试放置一个密钥,而另一个线程可以同时删除一个密钥(如果是相同的密钥,那么可能会出现问题)。在该方法中,还有更多情况可以得到竞争条件(具有各种后果)。

如果您有其他方法对表执行其他操作(即从中读取数据),这可能会变得更加复杂,并且它将使您的竞争条件比“仅”覆盖值更糟糕。

最后,你想问什么?您想知道如何避免竞争条件吗?地图类的其余部分做什么?

Yes.

(It seems that my answer has to be 30 characters or more)

The addId call can gave a race condition: one thread can try to put a key and another can remove the a key at the same time (if it's the same key, then it could be a problem). Within that method there are a couple more cases in which you can get a race condition (with various consequences).

This may further be complicated if you have other methods that do other things with the table, i.e. read from it, and it will make your race condition much worse than "just" an overwritten value.

Ultimately, what are you asking? Are you wondering how to avoid the race condition? What does the rest of your map class do?

李不 2024-11-24 03:57:01

如果您想保证在替换旧值时完成某些操作,那么竞争可能会导致不处理所有被覆盖的键。

if(table.containsKey(key)){
    Long oldValue = table.remove(key);
}
table.put(key, value);
if (oldValue != null)
    importantOperation(oldValue);

编辑:

它看起来像put 也会返回旧值(如果有的话),因此仍然不需要检查(正如其他人指定的那样)。在以下涉及赛车的尴尬情况下,该检查是必要的:

if(table.containsKey(key)){
    Long oldValue = table.remove(key);
    value = secretlyAdjustInput(oldValue, value)
}
table.put(key, value);

If you wanted to guarantee something is done with the old value when it is replaced, then the race could result in not handling all the overwritten keys.

if(table.containsKey(key)){
    Long oldValue = table.remove(key);
}
table.put(key, value);
if (oldValue != null)
    importantOperation(oldValue);

Edit:

It looks like put also returns the old value if there was one, so the check is still not necessary (as others have specified). The check would be necessary in the following awkward situation, which would have racing involved:

if(table.containsKey(key)){
    Long oldValue = table.remove(key);
    value = secretlyAdjustInput(oldValue, value)
}
table.put(key, value);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文