Java 在重入锁中等待条件
以下代码取自: 想象两个线程,消费者和生产者,一个使用Java 在重入锁中等待条件,java,synchronization,Java,Synchronization,以下代码取自: 想象两个线程,消费者和生产者,一个使用获取,一个将放在绑定缓冲区的单个实例上 假设消费者首先运行take(),在其中他锁定lock,现在循环notEmpty.await() 现在生产者如何才能进入put()方法,而不锁定消费者已经持有的锁 我错过了什么?线程等待某个条件时,锁是否“临时释放”?锁的可重入性到底意味着什么?无论是lock还是synchronized都允许一个线程在等待时放弃锁,而另一个线程可以获得锁。要停止等待,线程必须重新获取锁 注意:它们不会完全释放它,如果您进
获取
,一个将
放在绑定缓冲区
的单个实例上
假设消费者首先运行take()
,在其中他锁定lock
,现在循环notEmpty.await()代码>
现在生产者如何才能进入put()
方法,而不锁定消费者已经持有的锁
我错过了什么?线程等待某个条件时,锁是否“临时释放”?锁的可重入性到底意味着什么?无论是lock
还是synchronized
都允许一个线程在等待时放弃锁,而另一个线程可以获得锁。要停止等待,线程必须重新获取锁
注意:它们不会完全释放它,如果您进行堆栈跟踪,您可能会有多个线程同时持有锁,但最多有一个线程正在运行(其余线程将被阻塞)
从
与此条件相关联的锁将自动释放,当前线程出于线程调度目的被禁用,并处于休眠状态,直到发生以下四种情况之一:
- 其他一些线程为此条件调用signal()方法,而当前线程恰好被选为要唤醒的线程;或
- 其他一些线程为此条件调用signalAll()方法;或
- 其他线程中断当前线程,支持中断线程挂起;或
- 出现“虚假唤醒”李>
在所有情况下,在该方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,保证持有该锁
就重入性而言,这意味着持有某个锁的线程可以再次获得同一个锁。如果不是这样,则synchronized
方法将无法调用同一对象的另一个synchronized
方法
重新进入并不意味着理解您的问题。我在下面测试了使用单监视器和以下监视器的代码,它们的性能总是更好-在2核机器上测试,条件性能平均低于10-15%
final Object sync = new Object();
AtomicInteger add=new AtomicInteger();
AtomicInteger remove=new AtomicInteger();
final Object[] items = new Object[1];
int putptr, takeptr, count;
public void add(Object x) throws InterruptedException {
add.incrementAndGet();
synchronized (sync) {
while (count == items.length)
sync.wait();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
sync.notify();
}
}
public Object remove() throws InterruptedException {
remove.incrementAndGet();
synchronized (sync) {
while (count == 0)
sync.wait();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
sync.notify();
return x;
}
}
public static void main(String[] args) {
final BoundedBuffer bf=new BoundedBuffer();
Thread put =new Thread(){
public void run(){
try {
while(true)
bf.add(new Object());
} catch (InterruptedException e) {
}
}
};
put.start();
Thread take= new Thread(){
public void run(){
try {
while(true)
bf.remove();
} catch (InterruptedException e) {
}
}
};
take.start();
try {
Thread.sleep(1000L);
put.interrupt();
take.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("add:"+bf.add);
System.out.println("remove:"+bf.remove);
您能提供相关文档的链接吗?@PeterLawrey(其他人将等待)
或阻止?我认为他们应该处于阻塞状态`?你能解释一下这句话吗:“锁和同步都暂时允许其他人在等待时获得锁。”这对我来说没有意义。@Chin当锁的持有者在等待时,它释放了锁,可以被另一个线程持有。我想让人困惑的是,在你的句子中,“其他人”和“他们”并不是指同一个实体。我大约有两个人问了完全相同的问题,在JavaDoc上有完全相同的例子:)避免了我浪费时间。有时术语“递归锁”也用于可重入锁,请参阅。
final Object sync = new Object();
AtomicInteger add=new AtomicInteger();
AtomicInteger remove=new AtomicInteger();
final Object[] items = new Object[1];
int putptr, takeptr, count;
public void add(Object x) throws InterruptedException {
add.incrementAndGet();
synchronized (sync) {
while (count == items.length)
sync.wait();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
sync.notify();
}
}
public Object remove() throws InterruptedException {
remove.incrementAndGet();
synchronized (sync) {
while (count == 0)
sync.wait();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
sync.notify();
return x;
}
}
public static void main(String[] args) {
final BoundedBuffer bf=new BoundedBuffer();
Thread put =new Thread(){
public void run(){
try {
while(true)
bf.add(new Object());
} catch (InterruptedException e) {
}
}
};
put.start();
Thread take= new Thread(){
public void run(){
try {
while(true)
bf.remove();
} catch (InterruptedException e) {
}
}
};
take.start();
try {
Thread.sleep(1000L);
put.interrupt();
take.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("add:"+bf.add);
System.out.println("remove:"+bf.remove);