【问题标题】:Release lock of a map and grab lock of a value释放地图的锁定并获取值的锁定
【发布时间】:2013-06-18 23:20:13
【问题描述】:

我想在对象上有一个只打印尚未收到的数字的方法,因此我使用了以下代码。这个想法是我使用一个映射,它为每个整数存储一个 lock ,如果它已经在映射中,一个线程等待一个锁,否则它将以该整数作为键和一个 Integer 将一个新锁放入映射中对象作为值,

注意:我使用Integer(a)作为整数a的锁

问题是我想释放地图的锁,我想等待从地图中检索到的锁,但是race condition 发生了,有什么办法解决这个问题吗?

public class sync_print {
    public static void main(String[] args) {
        sync_print syobj = new sync_print();
        Thread t1 = new Thread(new worker(syobj, 10) , "thread 1");
        Thread t2 = new Thread(new worker(syobj, 10) , "thread 2");
        Thread t3 = new Thread(new worker(syobj, 4) , "thread 3");
        Thread t4 = new Thread(new worker(syobj, 5) , "thread 4");
        Thread t5 = new Thread(new worker(syobj, 5) , "thread 5");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }


    HashMap<Integer, Integer> lock_map = new HashMap<Integer , Integer>();
    void print(int a) throws InterruptedException{
        synchronized(lock_map){
            Integer lock = lock_map.get(a);
            if (lock != null){
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + " is waiting");
                    lock_map.notify();
                    lock.wait();
                }
            }else{
                lock_map.put(a, new Integer(a));
                System.out.println(a);
            }
        }
    }
}

class worker implements Runnable{
    int val;
    sync_print obj;
    public worker(sync_print obj , int v){
        this.val = v;
        this.obj = obj;
    }
    public void run() {
        try {
            obj.print(val);
        } catch (InterruptedException e) {}
    }
}

【问题讨论】:

    标签: java multithreading locking


    【解决方案1】:

    您可以通过将HashMap 替换为ConcurrentHashMap 来消除lock_map 上的锁定。将lock_map.put 更改为lock_map.putIfAbsent

    【讨论】:

    • 我不明白它与问题有什么关系,请您详细说明一下吗?
    • @Arian Hosseinzadeh 我不完全清楚你对lock_map 的锁定在做什么,但如果它可以防止多个线程同时调用lock_map.put,那么你可以使用@ 987654328@ 来代替 - 如果两个线程同时调用 putIfAbsent 则只有一个会成功。
    【解决方案2】:

    您的wait 不在循环中。请参阅elsewhere 了解为什么会产生问题。

    【讨论】:

      猜你喜欢
      • 2021-04-12
      • 2021-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多