Synchronized和Lock
1.Synchronized实现生产者消费者问题
package com.itheima.pc;
import java.util.concurrent.ThreadLocalRandom;
//synchronized
public class PC_demo01 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//定义资源类
//判断等待、业务、通知
class Data{
private int number=0;
//+1
public synchronized void increment() throws InterruptedException {
if (number!=0){
this.wait();
}
number++;
this.notifyAll();
System.out.println(Thread.currentThread().getName()+"=>"+number);
}
//-1
public synchronized void decrement() throws InterruptedException {
if (number==0){
this.wait();
}
number--;
this.notifyAll();
System.out.println(Thread.currentThread().getName()+"=>"+number);
}
}
问题存在:当上述的线程从A、B两个增加到四个A、B、C、D时,会发生虚假唤醒
解决办法:由jdk帮助文档可知,需将if判断修改为while循环,因为while会进行多次判断,从而解决虚假唤醒问题,保证多线程下依旧安全。
package com.itheima.pc;
import java.util.concurrent.ThreadLocalRandom;
//synchronized
public class PC_demo01 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//定义资源类
//判断等待、业务、通知
class Data{
private int number=0;
//+1
public synchronized void increment() throws InterruptedException {
while (number!=0){
this.wait();
}
number++;
this.notifyAll();
System.out.println(Thread.currentThread().getName()+"=>"+number);
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number==0){
this.wait();
}
number--;
this.notifyAll();
System.out.println(Thread.currentThread().getName()+"=>"+number);
}
}
2.Synchronized和Lock对比
synchronized:
- wait()
- notifyAll()
Lock:
Condition condition = lock.newCondition();
- await()
- signalAll()
3.Lock实现生产者消费者问题
与Synchronized相比Lock可以通过Condition实现精准通知,使多个线程可以进行有序执行
package com.itheima.pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PC_Lock {
public static void main(String[] args) {
Data1 data1 = new Data1();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data1.printfA();
}
}).start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data1.printfB();
}
}).start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data1.printfC();
}
}).start();
}
}
//资源类
//判断等待、业务、通知
class Data1{
private Lock lock=new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number=1; //1A 2B 3C
public void printfA(){
//加锁
lock.lock();
try {
//判断等待
if (number!=1){
//等待
condition1.await();
}
//业务
number=2;
System.out.println(Thread.currentThread().getName()+"=>"+"AAAAAAAA");
//通知B
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
public void printfB(){
lock.lock();
try {
//判断等待
if (number!=2){
//等待
condition2.await();
}
//业务
number=3;
System.out.println(Thread.currentThread().getName()+"=>"+"BBBBBBBBB");
//通知C
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printfC(){
lock.lock();
try {
//判断等待
if (number!=3){
//等待
condition3.await();
}
//业务
number=1;
System.out.println(Thread.currentThread().getName()+"=>"+"CCCCCCCCC");
//通知
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}