Java 以下代码中是否会出现竞态条件

Java 以下代码中是否会出现竞态条件,java,multithreading,Java,Multithreading,从多个线程调用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(ke

从多个线程调用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);
}
私有静态映射表;
静止的{
table=新的ConcurrentHashMap();
}
公共静态void addId(字符串键,长值){
if(表containsKey(键)){
表.删除(键);
}
表.put(键、值);
}

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

你为什么不这样做呢

public static void addId(String key, Long value){
    table.put(key, value);
}
put
仍将覆盖以前的任何条目



如果不希望多个线程同时执行该方法,请将该方法声明为“已同步”

没有任何东西可以阻止另一个线程在
containsKey
/
remove
put
之间放置某个值,因此在放置之前检查表是否已经包含键并不是真正的“安全”(或者更确切地说,没有真正的“意义”)

你为什么不这样做呢

public static void addId(String key, Long value){
    table.put(key, value);
}
put
仍将覆盖以前的任何条目


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

Yes

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

addId
调用可以给出一个竞争条件:一个线程可以尝试放置一个密钥,另一个线程可以同时删除该密钥(如果是同一个密钥,则可能是一个问题)。在该方法中,还有一些情况可以得到竞争条件(具有各种后果)

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

说到底,你在问什么?你想知道如何避免比赛状态吗?map类的其余部分做什么?

是的

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

addId
调用可以给出一个竞争条件:一个线程可以尝试放置一个密钥,另一个线程可以同时删除该密钥(如果是同一个密钥,则可能是一个问题)。在该方法中,还有一些情况可以得到竞争条件(具有各种后果)

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


说到底,你在问什么?你想知道如何避免比赛状态吗?map类的其余部分是做什么的?

是的,可能会发生竞争情况

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

    table.put(key, value);

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

是的,可能会发生争用情况

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

    table.put(key, value);

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

如果您想保证在替换旧值时使用旧值执行某些操作,则争用可能会导致无法处理所有覆盖的键

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

如果存在旧值,它看起来也会返回旧值,因此检查仍然是不必要的(正如其他人所指定的)。在以下可能涉及赛车的尴尬情况下,检查是必要的:

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

如果您想保证在替换旧值时使用旧值执行某些操作,那么竞争可能导致无法处理所有被覆盖的键

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

如果存在旧值,它看起来也会返回旧值,因此检查仍然是不必要的(正如其他人所指定的)。在以下可能涉及赛车的尴尬情况下,检查是必要的:

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

可以在一行中声明
。在一行中声明与在静态类代码中声明相同?是的,但需要一行而不是四行。我还将使
最终
您可以在一行中声明
。在一行中声明与在静态类代码中声明相同?是的,但它需要一行而不是四行。我还将使
成为最终的
类的其余部分只是有一个从表MapI返回值的访问器方法我想知道如何避免竞争条件,如果我的问题a看起来有点模糊,我道歉。这不仅仅是回答,谢谢!类的其余部分只是有一个访问器方法,它从表MapI返回一个值。我想知道如何避免竞争条件,如果我的问题a看起来有点模糊,我道歉。这不仅仅是回答,谢谢!