Java:在不同线程之间共享锁的最佳方式

问题描述 投票:0回答:2

是否建议将外部锁实现为在不同线程之间共享的类的属性?

例如我想要一个这样的实现:

public class Order {

    private final LinkedList<Food> order;
    private final int orderNum;
    private static int idGen;
    private final Lock lock;
    private final Condition isDone;

    public Order() {
        // TODO Auto-generated constructor stub
        this.order = new LinkedList<>();
        this.orderNum = ++idGen;
        this.lock =  new ReentrantLock();
        this.isDone = lock.newCondition();
    }

    public static Order createOrder(){
        return new Order();
    }

    public void add(Food food){
        synchronized (food) {
            order.add(food);
        }
    }

    public LinkedList<Food> getOrder() {
        return order;
    }

    public int getOrderNum() {
        return orderNum;
    }

    public synchronized boolean isEmpty(){
        return this.order.isEmpty();
    }
}

然后假设我有两个线程,分别称为 Customer 和 Cook。 Cook将尝试清空共享Order对象的LinkedList,而Customer将不断检查他的订单是否已完成,例如变空。我的目的是在共享 Order 对象内部使用锁。当 Cook 完成工作时,他会调用 order.getIsDone().signal() 来唤醒等待相同条件的 Customer 线程,例如 while(!order.isEmpty()) order.getIsDone().await();

我提出这个想法的原因是我想在绑定到某个 Order 对象的同时在两个线程之间共享相同的锁。但是,由于 Order 对象在不同线程之间共享,因此可能存在并发问题。因此,我不确定这种实施是否是明智的选择。

我能想到的另一种选择是用yield()替换order.getIsDone().await(),但它会导致一些性能损失,同时它更简单。

java concurrency locking
2个回答

-3
投票

锁定的整个想法是它们在线程之间共享!

所以,是的,锁定对象的一个字段,并使用条件来检查订单是否完成。

请记住,锁定后您需要始终解锁锁,因此图案是

lock.lock();
try {
...
} finally {
  lock.unlock();
}

您在循环中等待条件(但您已经知道)。

如果您已经在使用锁,则不需要在其他两个方法(isEmpty、add)上进行同步,因为锁速度更快,因此请改用它。

© www.soinside.com 2019 - 2024. All rights reserved.