Rumah  >  Soal Jawab  >  teks badan

java - 多线程并发情况下Map.containsKey() 判断有问题

有下面一段代码:

package test;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class TestContain extends Thread{

       private final String key = "key";
    
       private final static ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
        
        private static Object getLock(String lockName) {
            if (!locks.containsKey(lockName)) {
                //这一句会存在并发问题
                locks.put(lockName, new String("我是值"));
                System.out.println("加了一次");
            }
            return locks.get(lockName);
        }
        
        @Override
        public void run() {
            getLock(this.key);
        };
        
        public static void main(String[] args) {
            for (int i = 0; i < 20; i++) {
                new TestContain().start();;
            }
        }
}

输出结果:

加了一次
加了一次
加了一次

表明了Map.containsKey() 在多线程的情况下会判断不准确。

这是为什么呢? 有什么方法改进呢?

黄舟黄舟2744 hari yang lalu1146

membalas semua(3)saya akan balas

  • PHPz

    PHPz2017-04-18 10:51:53

    Dokumen

    ConcurrentHashMap mempunyai perenggan

    Operasi mendapatkan semula (termasuk <tt>get</tt>) secara amnya tidak
    menyekat, jadi mungkin bertindih dengan operasi kemas kini (termasuk

    <tt>put</tt> dan <tt>alih keluar</tt>). bermula.
    Kaedah get di dalam tidak dikunci Kaedah get hanya mendapat nilai kemas kini lengkap yang terkini.
    Jadi

    dalam kaedah subjek tidak mempunyai kunci untuk memastikan keselamatan benang. Dan nampaknya senario penggunaan

    bukan untuk menggunakan

    untuk memastikan operasi kemas kini hanya dilakukan sekali, tetapi menggunakan

    untuk memastikan. locks.containsKey(lockName)

    balas
    0
  • 高洛峰

    高洛峰2017-04-18 10:51:53

    ConcurrentMap menjamin atomicity bagi satu operasi, bukan berbilang operasi.

    Fungsi getLock anda mengandungi berbilang operasi ConcurrentMap tidak boleh mengembangkan julat penyegerakannya Anda perlu melaksanakan kunci getLock sendiri.

    balas
    0
  • 迷茫

    迷茫2017-04-18 10:51:53

    Gunakan kaedah putIfAbsent.

    balas
    0
  • Batalbalas