假设我有这个方法
/*1*/ public synchronized void method1() throws InterruptedException {
while (condition)
/*2*/ wait();
/*3*/ notify();
}
假设我们有一个Thread 1
处于第二行等待条件,那么线程1将处于WAITING
状态。
现在Thread 2
进入,它不满足条件,所以它绕过while循环,然后Thread 2
在第3行调用notify
,然后Thread 1
应该将其状态从WAITING
更改为BLOCKED
,直到Thread 2
完全退出。
假设现在,在线程2完全退出之前,Thread 3
是同步块之外的BLOCKED
,以获取监视器。
Thread 3
是否可能在Thread 1
之前获取锁?对于Thread 4
和Thread 5
等等,它可以是相同的吗?在这种情况下,Thread-1
将处于饥饿状态。
这在概念上可行吗?
编辑:如果是这种情况,我该如何防止饥饿?
如果是这种情况,我该如何防止饥饿?
使用synchronized
关键字无法阻止它。然而,您可以使用ReentrantLock
,因为它允许";"公平";锁定
private final ReentrantLock lock = new ReentrantLock(true); // fair lock
private final Condition sync = lock.newCondition();
public void method1() throws InterruptedException {
lock.lock();
try {
while (condition)
sync.await();
sync.signal();
} finally {
lock.unlock();
}
}
请记住,公平的锁是有价格的,你应该有真正的理由使用它
来自JavaDochttps://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
这个类的构造函数接受一个可选的公平性参数。当设置为true时,在争用下,锁定有利于授予对等待时间最长的线程的访问权限。否则,此锁不能保证任何特定的访问顺序。使用由许多线程访问的公平锁的程序可能显示出比使用默认设置的程序更低的总体吞吐量(即,更慢;通常慢得多(,但获得锁的时间差异较小,并保证不会出现饥饿。但是,请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程中的一个线程可以连续多次获得它,而其他活动线程没有进行并且当前没有持有该锁。还要注意,不计时的tryLock方法不尊重公平性设置。如果锁可用,即使其他线程正在等待,它也会成功。