我是一名java初学者,我在java中学习Thread
时编写下面的代码。我想,如果我锁定Resource.set()
并注释掉Lock.unlock()
,Resource.out()
中的代码就无法执行,因为当我想执行方法时我无法解锁。顺便说一句,无论我在set()
还是out()
中注释解锁,程序都会以这种方式执行:
主题[线程1,5,主] .... ....生产
chicken1 螺纹[线程2,5,主] ....消耗.......... chicken1
螺纹[线程0,5,主] .... ....生产
chicken2 线程[Thread-3,5,main] ....消耗.......... chicken2 ......
我想很长一段时间并且不了解它。我刚刚学会了,也许我的理解有误,所以我希望有人帮忙。 请原谅我可怜的英语。非常感谢你。我的代码在这里:
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();
}
}
}
}
}
答案 0 :(得分:1)
在制作人和消费者中,您通过
重复调用lock.await
while (true) {
//
}
来自doc,当您致电lock.await
时:
与此条件关联的锁定以原子方式释放
因此,无论您是否注释lock.unlock
,生产者和消费者都不会被阻止。
P.S。使用以下代码记录有关获取和释放锁定的更多详细信息:
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();
}
}
}
}
}
答案 1 :(得分:0)
FirstOfAll,"如果我锁定Resource.set()并注释掉Lock.unlock(),则无法执行Resource.out()中的代码"。你的陈述是错误的。
让我澄清一下原因,
在您发布的代码中,out()
无法解锁。我假设你没有问题,其中一个Consumer
线程(t2
或t3
)在获取锁时没有问题。
让我们说t2
获取锁定,同时输入out()
方法并且在退出out()
方法时没有释放锁定。但是你忽略了out()
方法在run()
Runnable的Consumer
方法中的无限循环中执行的事实。因此当t2
退出out()
时,睡眠时间为500
毫秒;它仍然拥有锁。当它在下一次迭代中进入out()
方法时,它会在已有的同一个锁上执行Lock.lock()
。由于锁是Reentrant
锁,它继续并执行await()
释放锁定;等待锁定的其他线程(Producer
个线程)有机会获得锁定。