繁体   English   中英

使用tryLock()以及wait()和notify()/ notifyAll()

[英]using tryLock() together with wait() and notify()/notifyAll()

我是线程技术的新手,正在这里尝试一种混合方法。 我有下面的代码。

if(lock.tryLock())
{
    try
    {
        //do some actions
        lock.notifyAll(); // error throwing line
    }
    finally
    {
        lock.unlock();
    }
}

如果我像这样运行程序,则会在该错误引发行引发非法监视器异常。 但是如果我在下面的同步块中调用它会起作用。

if(lock.tryLock())
{
    try
    {
        //do some actions

        synchronized ( lock )
        {
            lock.notifyAll(); 
        }
    }
    finally
    {
        lock.unlock();
    }
}

我的问题是,因为我将tryLock设置为true,这是否意味着我已经获得了锁并且可以安全地调用wait()和notify()方法? 提前致谢..

在这里忘记“混合方法”,这是行不通的。

每个对象都有一个隐式锁。 其中包括诸如ReentrantLock之类的Lock类的对象。 调用wait and notify始终使用隐式锁,这些方法不使用您要对其进行调用的Lock对象的锁定功能。 在对象中,wait,notify和notifyAll方法被声明为本地方法和最终方法。

为了获得等待并通知工作,您必须在锁定对象上进行同步,而通过tryLock之类的方法进行的锁定将是无关紧要的,最终在功能上等同于final Object lock = new Object(); ,只会更加令人困惑。

锁对象具有它们自己的等效项,如果您使用的是java.util.concurrent.locks.Lock然后从锁java.util.concurrent.locks.Lock获取一个条件,然后调用await(等效于wait)和signal / signalAll(等效于notify / notifyAll)。

使用Lock对象,您可以具有多个条件,从而允许您发信号通知等待锁定的线程子集。 因此,您几乎不需要隐式锁定代码需要notifyAll的任何地方的signalAll。

例如,如果您查看ArrayBlockingQueue的实现方式,它使用ReentrantLock,那么对于使用者来说有一个条件,对于生产者来说有另一个条件:

/** Main lock guarding all access */
final ReentrantLock lock;

/** Condition for waiting takes */
private final Condition notEmpty;

/** Condition for waiting puts */
private final Condition notFull;

public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull =  lock.newCondition();
}

使用隐式锁的等效代码必须调用notifyAll以避免丢失通知,因为我们不知道被通知的线程是生产者还是使用者,但是在单独的条件下,我们知道将通知哪种线程。 例如,出队代码在notFull条件下调用信号,最多唤醒一个线程:

/**
 * Extracts element at current take position, advances, and signals.
 * Call only when holding lock.
 */
private E dequeue() {
    // assert lock.getHoldCount() == 1;
    // assert items[takeIndex] != null;
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    E x = (E) items[takeIndex];
    items[takeIndex] = null;
    if (++takeIndex == items.length)
        takeIndex = 0;
    count--;
    if (itrs != null)
        itrs.elementDequeued();
    notFull.signal();
    return x;
}

暂无
暂无

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

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