Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentHashMap上的同步_Java_Multithreading_Concurrency_Synchronized_Java.util.concurrent - Fatal编程技术网

Java ConcurrentHashMap上的同步

Java ConcurrentHashMap上的同步,java,multithreading,concurrency,synchronized,java.util.concurrent,Java,Multithreading,Concurrency,Synchronized,Java.util.concurrent,在我的应用程序中,我使用的是ConcurrentHashMap,我需要原子地执行这种类型的“如果不存在自定义put”方法 public boolean putIfSameMappingNotExistingAlready(String key, String newValue) { String value; synchronized (concurrentHashMap) { if (value = concurrentHashMap.putIfAbsent(key,

在我的应用程序中,我使用的是ConcurrentHashMap,我需要原子地执行这种类型的“如果不存在自定义put”方法

public boolean putIfSameMappingNotExistingAlready(String key, String newValue) {
    String value;
    synchronized (concurrentHashMap) {
    if (value = concurrentHashMap.putIfAbsent(key, newValue)) == null) {
          // There was no mapping for the key
      return true;
      } else { if (value.equals(newValue)) {
                // The mapping <key, newValue> already exists in the map
                return false;
            } else {
                concurrentHashMap.put(key, newValue);
                return true;
            }
        }
     }
    } 
public boolean putIfSameMappingNotExistingAlready(字符串键,字符串newValue){
字符串值;
已同步(concurrentHashMap){
if(value=concurrentHashMap.putIfAbsent(key,newValue))==null){
//没有密钥的映射
返回true;
}else{if(value.equals(newValue)){
//映射已存在于映射中
返回false;
}否则{
concurrentHashMap.put(键,newValue);
返回true;
}
}
}
} 
我(在并发包文档中)读到

并发集合是线程安全的,但不受单个排除锁的控制

因此,您无法在ConcurrentHashMap上获得独占锁

我的问题是:

  • 上面的代码是线程安全的吗?在我看来,似乎可以保证同步块中的代码只能由单个线程同时执行,但我想确认一下

  • 在这种情况下,使用Collections.synchronizedMap()而不是ConcurrentHashMap不是更“干净”吗


  • 非常感谢

    以下代码使用比较和设置循环(如SlakS所建议的)来实现线程安全(注意无限循环):


    以下代码使用比较和设置循环(如SlakS所建议的)来实现线程安全(注意无限循环):


    通过像这样对整个集合进行同步,您实际上是在用自己的钝器方法替换并发集合中的细粒度同步


    如果您没有在其他地方使用并发保护,那么您可以使用标准的
    HashMap
    ,并将其包装到您自己的同步中。使用
    synchronizedMap
    可能会起作用,但不会涵盖多步骤操作,例如上面的放置、检查、放置操作。

    通过对整个集合进行同步,就像您基本上用自己的钝器方法替换并发集合中的细粒度同步一样



    如果您没有在其他地方使用并发保护,那么您可以使用标准的
    HashMap
    ,并将其包装到您自己的同步中。使用
    synchronizedMap
    可能会起作用,但不会涵盖多步操作,例如上面的放置、检查、放置位置。

    它真的是“concurrentHashMap.putIfAbsent(msg,msg)”吗?@isnot2bad不,我更正了它,谢谢您使用比较和设置循环而不是锁@ovdsrn您在编辑中建议的代码将不起作用,因为如果此键已经有映射,则putIfAbsent不会执行任何操作。@isnot2bad您完全正确,愚蠢的我,我将删除编辑,因为它毫无意义。它真的是“concurrentHashMap.putIfAbsent(msg,msg)”吗?@isnot2bad否,我更正了它,谢谢你使用比较和设置循环而不是锁@ovdsrn您在“编辑”中建议的代码将不起作用,因为如果该键已存在映射,则putIfAbsent不会执行任何操作。@Isnot2如果您完全正确,愚蠢的我,我将删除该编辑,因为它毫无意义。您的建议不会让您知道映射是否已存在于映射中。您将只能确定是否存在该键的映射。注意,如果Java 7,
    nullSafeEquals()
    可以替换为
    Objects.equals()
    @fge Fine。我不确定它是Java 7还是Java 8。+1我唯一要说的是
    concurrentHashMap。putIfAbsent
    每次都会获得一个锁,如果有许多
    replace
    对象,这可能会降低吞吐量。equals
    调用正在进行。我会先获取
    oldValue
    ,然后在执行PutiAbsent测试(重新分配oldValue时)时,如果它为null,我会使用
    putiAbsent
    的返回值完全删除
    get
    。(如果条目已经存在,
    putIfAbsent
    应该像
    get
    一样处理吞吐量问题)。现在代码更简单了。您的建议不会让您知道映射是否已经在映射中。您将只能确定是否存在该键的映射。注意,如果Java 7,
    nullSafeEquals()
    可以替换为
    Objects.equals()
    @fge Fine。我不确定它是Java 7还是Java 8。+1我唯一要说的是
    concurrentHashMap。putIfAbsent
    每次都会获得一个锁,如果有许多
    replace
    对象,这可能会降低吞吐量。equals
    调用正在进行。我会先获取
    oldValue
    ,然后在执行PutiAbsent测试(重新分配oldValue时)时,如果它为null,我会使用
    putiAbsent
    的返回值完全删除
    get
    。(如果条目已经存在,
    putIfAbsent
    应该像
    get
    一样处理吞吐量问题)。现在代码更简单了。
    /**
     * Updates or adds the mapping for the given key.
     * Returns true, if the operation was successful and false,
     * if key is already mapped to newValue.
     */
    public boolean updateOrAddMapping(String key, String newValue) {
        while (true) {
            // try to insert if absent
            String oldValue = concurrentHashMap.putIfAbsent(key, newValue);
            if (oldValue == null) return true;
    
            // test, if the values are equal
            if (oldValue.equals(newValue)) return false;
    
            // not equal, so we have to replace the mapping.
            // try to replace oldValue by newValue
            if (concurrentHashMap.replace(key, oldValue, newValue)) return true;
    
            // someone changed the mapping in the meantime!
            // loop and try again from start.
        }
    }