简体   繁体   English

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

[英]Java: best way to share Lock between different threads

Is it advisable to implement a extrinsic lock as an attrubite of a class that will be shared between different threads? 是否建议将外部锁实现为将在不同线程之间共享的类的属性?

For example I would like to have a implementation like this: 例如,我想要一个这样的实现:

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();
    }
}

Then assume that I have two threads called Customer and Cook. 然后假设我有两个线程,分别称为Customer和Cook。 Cook will try to empty the LinkedList of the shared Order object, while Customer will constantly check whether his order has been fulfilled, eg become empty. Cook将尝试清空共享Order对象的LinkedList,而Customer将不断检查他的订单是否已完成,例如变为空。 My purpose is to use a lock inside shared Order object. 我的目的是在共享Order对象内使用锁。 When Cook finish his job, he would call order.getIsDone().signal() to awake Customer thread awaiting with the same condition, eg while(!order.isEmpty()) order.getIsDone().await(); 当Cook完成工作后,他将调用order.getIsDone()。signal()唤醒处于相同条件下等待的客户线程,例如while(!order.isEmpty())order.getIsDone()。await();。

The reason that I came up with this idea is that I want to share the same lock between two threads while bounding to a certain Order object. 我提出这个想法的原因是,我想在绑定到某个Order对象的同时在两个线程之间共享相同的锁。 However, since Order object is shared between different threads, it might have concurrent issue. 但是,由于Order对象在不同线程之间共享,因此可能存在并发问题。 So, I am not sure this impelementation is a wise choice. 因此,我不确定这种实施是否是一个明智的选择。

An alternative I can think of would be replacing order.getIsDone().await() with yield(), but it will cause some performance loss while it's much simplier. 我能想到的另一种方法是用yield()替换order.getIsDone()。await(),但这会导致一些性能损失,但要简单得多。

The whole idea of locks it that they are shared between threads! 锁定的整个思想是它们在线程之间共享!

So yes, do lock on the lock which is a field of your object, and use the condition to check if the order is completed. 因此,是的,请锁定对象的字段锁,并使用条件检查订单是否完成。

Just remember you need always unlock the lock after locking so the pattern is 只要记住您需要始终在锁定后解锁锁,这样就可以

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

You wait on your condition in the loop (but you already know about it). 您在循环中等待条件(但是您已经知道了)。

If you are already using lock, you dont need synchronized on your other two methods (isEmpty, add) as lock is faster so use it instead. 如果您已经在使用锁,则不需要在其他两种方法(isEmpty,add)上进行同步,因为锁的速度更快,因此请使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM