传统的生产者消费者模型:一个生产者 一个消费者,当生产者3一个时,消费者消费一个。
package com.java.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 资源类
*/
class ShareData{
private int number=0;
private Lock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
public void increment() throws Exception{
lock.lock();
try{
//1.判断
while(number!=0){
//等待,不能生产
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
condition.signalAll();
}catch (Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void decrement() throws Exception{
lock.lock();
try{
//1.判断
while(number==0){
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
condition.signalAll();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
public class ProdConsumer_TraditionDemo {
public static void main(String[] args) {
ShareData shareData=new ShareData();
new Thread(()->{
for(int i=0;i<5;i++){
try {
shareData.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"AAA").start();
new Thread(()->{
for(int i=0;i<5;i++){
try {
shareData.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"BBB").start();
}
}
输出结果:
synchronized和lock有什么区别?用新的lock有什么好处?
区别:
1.原始构成:synchronized是关键字,属于JVM层面。monitorenter(底层是通过monitor对象完成,其实wait/notify等方法也依赖与monitor对象,只有在同步块或方法中才能调用wait/notify等方法。);而Lock是具体类(java.util.concurrent.Locks.Lock)是api层面的锁。
2.使用方法:synchronized不需要用户去手动释放锁,当synchronIzed代码执行完成后系统会自动让线程释放对锁的占用。ReentrantLock则需要用户去手动释放锁,若没有主动释放锁,就有可能导致出现死锁现象。
3.等待是否可中断:synchronized不可中断,除非抛出异常或者正常运行完成。ReentrantLock可中断,1.设置超时方法,tryLock(Long timeout,TimeUtil unit);2.LockInterruptibly()放代码块中,调用interrupt()方法可中断。
4.加锁是否公平:synchronized为非公平锁;ReentrantLock两者都可以,默认非公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁。
5.锁绑定多个条件condition
synchronized没有;ReentrantLock用来实现分组唤醒需要唤醒的线程,可以精确唤醒,而不是像synchronized要么唤醒全部要么随机唤醒一个。
就第五点来说:Conditon:当A运行了输出5次后精确唤醒B线程,B线程输出10次后唤醒C,C线程输出15次后唤醒A线程。持续输出5轮。
package com.java.thread;
import org.omg.PortableServer.THREAD_POLICY_ID;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ShareResource{
private int number=1;//A 1 B 2 C 3
private Lock lock=new ReentrantLock();
private Condition c1=lock.newCondition();
private Condition c2=lock.newCondition();
private Condition c3=lock.newCondition();
public void print5(){
lock.lock();
try{
//1.判断
while(number!=1){
c1.await();
}
//2.干活
for(int i=1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
//3.唤醒
number++;
c2.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void print10(){
lock.lock();
try{
while(number!=2){
c2.await();
}
for(int i=1;i<=10;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
number++;
c3.signal();
}catch (Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void print15(){
lock.lock();
try{
while(number!=3){
c3.await();
}
for(int i=1;i<=15;i++){
System.out.println(Thread.currentThread().getName()+"\t"+i);
}
number=1;
c1.signal();
}catch (Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
public class SyncAndReentrantLockDemo {
public static void main(String[] args) {
ShareResource shareResource=new ShareResource();
for(int i=0;i<5;i++){
new Thread(()->{
shareResource.print5();
},"A").start();
new Thread(()->{
shareResource.print10();
},"B").start();
new Thread(()->{
shareResource.print15();
},"C").start();
}
}
}