1 线程间通信
1.1 wait()和notify()完成通信
完成一个例子,线程A和线程B对变量value进行操作,value初始值为0,线程A当value的值为0时给其加1
线程B当value的值为1时给其减1,通过wait()和notify()来完成线程A和线程B的通信
public class Value {
private int number;
public Value() {}
public synchronized void incr() throws InterruptedException {
if(number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + ": " + number);
this.notifyAll();
}
public synchronized void decr() throws InterruptedException {
if (number != 1) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + ": " + number);
this.notifyAll();
}
}

1.2 wait()的虚假唤醒问题
将上述的程序增加两个线程,分别完成自增和自减,理想中由于if的存在,结果仍然是1和0交替出现,但是执行后可以看到:

之所以产生上述的问题,是由于wait()方法的虚假唤醒问题,考虑如下情况:
考虑A拿到锁开始执行 此时判断通过 number++ number=1 notifyAll()
C拿到锁开始执行 此时判断未通过 C释放锁等待
A拿到锁开始执行 此时判断未通过 A释放锁等待
C拿到锁开始执行 从上次wait()之后的代码继续执行 number++ number=2 notifyAll()
为了解决wait()的虚假唤醒问题,只需线程每次醒来后再进行一次判断即可
public synchronized void incr() throws InterruptedException {
while (number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + " :" + number);
this.notifyAll();
}
1.3 Lock完成通信
使用Lock接口的实现类ReentrantLock作为锁
并通过condition的await()/signal()完成线程间的通信
public class Value {
private final ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private int number;
public void incr() {
lock.lock();
try {
while (number != 0) {
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + " :" + number);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void decr() {
lock.lock();
try {
while (number != 1) {
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + " :" + number);
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
1.4 线程间定制化通信
完成示例,A线程先打印5次,B线程再打印10次,C线程再打印15次 依次循环此过程10轮
通过多个Condition和flag来完成确定的唤醒
public class Test {
// 通信判断用标志位
private int flag = 1;
private final ReentrantLock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
public void taskA(int loop) {
lock.lock();
try {
while (flag != 1) {
c1.await();
}
for(int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i + " loop:" + loop);
}
flag = 2;
c2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
...



被折叠的 条评论
为什么被折叠?



