1.先从一个题目说起:两个线程对一个初始值为0的变量擦欧洲哦,实现一个线程加,一个线程-,
以下是这个题目的实现
public class ThreadDemo02 {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<20;i++){
try {
shareData.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"A").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<20;i++){
try {
shareData.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"B").start();
/* new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<20;i++){
try {
shareData.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"C").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<20;i++){
try {
shareData.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"D").start();*/
}
}
class ShareData {
private int number = 0;
public synchronized void increment() throws InterruptedException {
if (number == 1) { //这里如果用if,可能会引起线程的虚假唤醒
this.wait();
}
//消费
System.out.println(Thread.currentThread().getName() + " " + ++number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (number == 0) {
this.wait();
}
//生产
System.out.println(Thread.currentThread().getName() + " " + --number);
this.notifyAll();
}
}
如果只用两个线程去调用,结果完全正确,
但是如果四个线程去调用,可能回出现虚假唤醒; JDK中也对WAIT方法进行了介绍
也给出了建议的方法,用while代替if, 下次进入线程的时候在做一次判断,防止虚假唤醒;
2.第二种方式,用lock替带 synchronized;如下代码
public class ThreadDemo02 {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
shareData.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
shareData.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
shareData.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "C").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
shareData.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "D").start();
}
}
class ShareData {
private int number = 0;
private Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void increment() throws InterruptedException {
lock.lock();
try {
while (number == 1) { //这里如果用if,可能会引起线程的虚假唤醒
//替代wait()
condition.await();
}
//消费
System.out.println(Thread.currentThread().getName() + " " + ++number);
//喚醒
condition.signalAll();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
lock.lock();
try {
while (number == 0) {
condition.await();
}
//生产
System.out.println(Thread.currentThread().getName() + " " + --number);
condition.signalAll();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
/* public synchronized void increment() throws InterruptedException {
if (number == 1) { //这里如果用if,可能会引起线程的虚假唤醒
this.wait();
}
//消费
System.out.println(Thread.currentThread().getName() + " " + ++number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (number == 0) {
this.wait();
}
//生产
System.out.println(Thread.currentThread().getName() + " " + --number);
this.notifyAll();
}*/
}