1、线程通信-交替操作sync实现
变量初始值为0
a线程对变量进行++操作后,通知b线程对变量进行—操作
b线程对变量进行—操作后,通知a线程对变量进行++操作
使用synchronized与Lock两种方式实现。
synchronized代码实现:
class STicket{
private int target=0;
public synchronized void incr(){
if(target!=0){
try {
//等待其他线程进行操作
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
target++;
System.out.println(Thread.currentThread().getName()+"::"+target);
//操作完毕后,唤醒其他线程进行操作
this.notifyAll();
}
public synchronized void decr(){
if(target!=1){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
target--;
System.out.println(Thread.currentThread().getName()+"::"+target);
this.notifyAll();
}
}
public class SyncTest {
public static void main(String[] args) {
STicket ticket=new STicket();
new Thread(()->{
for (int i=0;i<10;i++){
ticket.incr();
}
},"线程1").start();
new Thread(()->{
for (int i=0;i<10;i++){
ticket.decr();
}
},"线程2").start();
}
}
2、线程通信synchronized虚假唤醒
创建线程3:对target进行++操作
创建线程4:对target进行—操作
虚假唤醒情况说明:当线程1对target操作完毕后target=1,恰好此时线程3抢到执行权,此时线程3进入等待状态target=1,此时线程2抢到执行权对target进行操作后target=0,线程1再次抢到执行权操作完毕后唤醒线程target=1,刚好被线程3抢到执行权进行++后,此时target=2,同理—操作也如此。
解决方案:将 if 判断修改为 while 循环
while(target!=0){
this.wait();//异常处理省略
}
while(target!=1){
this.wait();
}
3、线程通信-交替操作Lock实现
class Share {
private int target = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void incr() throws InterruptedException {
lock.lock();
try {
while (target != 0) {
//等待其他线程进行操作
condition.await();
}
target++;
System.out.println(Thread.currentThread().getName() + "::" + target);
//唤醒其他线程
condition.signalAll();
} finally {
lock.unlock();
}
}
public void decr() throws InterruptedException {
lock.lock();
try {
while (target != 1) {
condition.await();
}
target--;
System.out.println(Thread.currentThread().getName() + "::" + target);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
public class LockDemo {
public static void main(String[] args) {
Share share = new Share();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程1").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程2").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程3").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "线程4").start();
}
}