[英]Lock and Condition about thread communication in java
I'm a java beginner and I write below code while learning Thread
in java.我是一名 Java 初学者,我在学习 Java
Thread
编写了以下代码。 I think, if I lock in Resource.set()
and comment out the Lock.unlock()
, the code in Resource.out()
can't be executed because I can't unlock in when I want to execute out method.我认为,如果我锁定
Resource.set()
并注释掉Lock.unlock()
,则Resource.out()
的代码无法执行,因为我在想要执行 out 方法时无法解锁。 BTW, whether I comment out the unlock in the set()
or in out()
, the program will execute in this way:顺便说一句,无论我在
set()
还是out()
注释掉解锁,程序都会以这种方式执行:
Thread[Thread-1,5,main]....Produce....chicken1
Thread[Thread-1,5,main]....生产....chicken1
Thread[Thread-2,5,main]....Consume..........chicken1Thread[Thread-2,5,main]....Consume.........chicken1
Thread[Thread-0,5,main]....Produce....chicken2Thread[Thread-0,5,main]....生产....chicken2
Thread[Thread-3,5,main]....Consume..........chicken2 ......Thread[Thread-3,5,main]....Consume.........chicken2 ......
I think a long time and don't understand about it.想了很久,还是不明白。 I just learned it, maybe I have a wrong understanding,so I hope someone's help.
刚学的,可能理解有误,希望各位大侠指教。 Please forgive my poor English.
请原谅我糟糕的英语。 Thank you very much.
非常感谢。 My code is here:
我的代码在这里:
package Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadStudying {
public static void main(String[] args) {
Resource r = new Resource();
Thread t0 = new Thread(new Producer(r));
Thread t1 = new Thread(new Producer(r));
Thread t2 = new Thread(new Consumer(r));
Thread t3 = new Thread(new Consumer(r));
t0.start();
t1.start();
t2.start();
t3.start();
}
static class Resource {
private String name;
private int count = 1;
boolean isOut = false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition consu_con = lock.newCondition();
public void set(String name) {
lock.lock();
try {
while (isOut) {
try {
pro_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
System.out.println(Thread.currentThread() + "....Produce...." + this.name);
count++;
isOut = true;
consu_con.signal();
}
finally {
lock.unlock();
}
}
public void out() {
lock.lock();
try {
while (!isOut) {
try {
consu_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "....Consume.........." + this.name);
isOut = false;
pro_con.signal();
}
finally {
//lock.unlock();
}
}
}
static class Producer implements Runnable {
Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while (true) {
r.set("chicken");
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
Resource r;
Consumer(Resource r) {
this.r = r;
}
@Override
public void run() {
while (true) {
r.out();
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
In both producer and consumer, you are calling lock.await
repeatly by在生产者和消费者中,您都通过
lock.await
重复调用lock.await
while (true) {
//
}
From the doc , when you call lock.await
:从文档中,当您调用
lock.await
:
The lock associated with this Condition is atomically released
与此 Condition 关联的锁被自动释放
So, whether you comment out lock.unlock
or not, both producer and consumer will not be blocked.所以,不管你是否注释掉
lock.unlock
,生产者和消费者都不会被阻塞。
PS Use below code to log more details about getting and releasing lock: PS使用以下代码记录有关获取和释放锁的更多详细信息:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadStudying {
public static void main(String[] args) {
Resource r = new Resource();
Thread t0 = new Thread(new Producer(r), "Producer 1");
Thread t1 = new Thread(new Producer(r), "Producer 2");
Thread t2 = new Thread(new Consumer(r), "Consumer 1");
Thread t3 = new Thread(new Consumer(r), "Consumer 2");
t0.start();
t1.start();
t2.start();
t3.start();
}
static class Resource {
private String name;
private int count = 1;
boolean isOut = false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition consu_con = lock.newCondition();
public void set(String name) {
System.out.println(Thread.currentThread() + "before lock");
lock.lock();
System.out.println(Thread.currentThread() + "get lock");
try {
while (isOut) {
try {
System.out.println(Thread.currentThread() + "release lock");
pro_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
System.out.println(Thread.currentThread() + "....Produce...." + this.name);
count++;
isOut = true;
consu_con.signal();
}
finally {
}
}
public void out() {
System.out.println(Thread.currentThread() + "before lock");
lock.lock();
System.out.println(Thread.currentThread() + "get lock");
try {
while (!isOut) {
try {
System.out.println(Thread.currentThread() + "release lock");
consu_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "....Consume.........." + this.name);
isOut = false;
pro_con.signal();
}
finally {
//lock.unlock();
}
}
}
static class Producer implements Runnable {
Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while (true) {
r.set("chicken");
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
Resource r;
Consumer(Resource r) {
this.r = r;
}
@Override
public void run() {
while (true) {
r.out();
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
FirstOfAll, "if I lock in Resource.set() and comment out the Lock.unlock(), the code in Resource.out() can't be executed ".首先,“如果我在 Resource.set() 中锁定并注释掉 Lock.unlock(),则 Resource.out() 中的代码将无法执行”。 This statement of yours is wrong.
你的这个说法是错误的。
Let me clarify why,让我澄清为什么,
In your posted code, where out()
has no unlock.在您发布的代码中,
out()
没有解锁。 I assume you have no problem that one of the Consumer
threads ( t2
or t3
) have no problem in acquiring the lock.我假设您没有问题,
Consumer
线程之一( t2
或t3
)在获取锁时没有问题。
So lets say t2
acquired the lock, while entering out()
method and didn't release the lock while exiting out()
method.因此,假设
t2
在进入out()
方法时获取了锁,并且在退出out()
方法时没有释放锁。 But you overlooked the fact that out()
method is executed in infinite loop inside run()
method of Consumer
Runnable.但是您忽略了
out()
方法在Consumer
Runnable 的run()
方法内无限循环执行的事实。 So when t2
exits out()
, sleep of 500
milliseconds;所以当
t2
退出out()
,休眠500
毫秒; its still in possession of the lock.它仍然拥有锁。 When it enters the
out()
method in its next iteration, it executes Lock.lock()
on the same lock it already has.当它在下一次迭代中进入
out()
方法时,它会在它已经拥有的同一个锁上执行Lock.lock()
。 Since the lock is Reentrant
Lock, it proceeds and executes await()
where it releases the lock;由于锁是
Reentrant
锁,所以它继续执行await()
,在那里释放锁; and the other threads( Producer
threads) waiting on the lock gets chance to acquire the lock.等待锁的其他线程(
Producer
线程)有机会获得锁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.