//源码:构造方法 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
package com.cyl.demo01; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SafeTicketDemo02 { public static void main(String[] args) { //并发,多线程同时操作一个资源类,将资源类丢入线程 Ticket02 ticket = new Ticket02(); //@FunctionInterface 函数式接口 // jdk1.8之后使用lambda表达式简化书写:(parameter)->{code} new Thread(()->{ for (int i = 0; i < 20; i++) ticket.sale(); },"a0").start(); new Thread(()->{ for (int i = 0; i < 20; i++) ticket.sale(); },"a1").start(); new Thread(()->{ for (int i = 0; i < 20; i++) ticket.sale(); },"a2").start(); } } //资源类 //Lock锁 class Ticket02{ // 1.属性,方法(OOP思想) private int ticketNums = 20; Lock lock = new ReentrantLock(); //卖票的方法 public void sale() { lock.lock();//加锁 try {//业务代码 if (ticketNums > 0) { System.out.println(Thread.currentThread().getName()+ "卖出了"+(ticketNums--)+"张票,剩余"+ticketNums); } }catch (Exception e) { e.printStackTrace(); }finally { lock.unlock();//解锁 } } }
##Synchronized与Lock锁的区别
//源码:构造方法 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
package com.cyl.PC; /** * 线程之间的通信问题(线程交替执行),等待唤醒,通知唤醒 * 单例模式,生产者和消费者,死锁 * A对num进行+1,告诉B之后,B对num进行-1 * */ public class A { 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 num = 0; //+1 public synchronized void increment() throws InterruptedException { if (num != 0) { //等待 this.wait(); } num ++ ; System.out.println(Thread.currentThread().getName()+"==>"+num); //通知其他线程,我+1执行结束了 this.notifyAll(); } //+2 public synchronized void decrement() throws InterruptedException { if (num == 0) { //等待 this.wait(); } num -- ; System.out.println(Thread.currentThread().getName()+"==>"+num); //通知其他线程,我-1执行结束了 this.notifyAll(); } }
线程变多,即就产生了虚假唤醒问题,将if判断改为while循环判断即可。
class Data02 { //数字,资源类 private int num = 0; Lock lock = new ReentrantLock(); //condition:精准通知和唤醒线程 Condition condition = lock.newCondition(); public void decrement() throws InterruptedException { try { lock.lock(); //业务代码 while (num == 0) { //等待 condition.await(); } //通知其他线程 condition.signalAll(); }catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
package com.cyl.PC; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 线程间通信,实现顺序执行 * A执行完之后通知B,B执行完之后通知C,C执行完通知A */ public class C { public static void main(String[] args) { Data03 data = new Data03(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.printA(); } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.printB(); } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data.printC(); } },"C").start(); } } //资源类 class Data03 {//Lock private Lock lock = new ReentrantLock(); Condition condition01 = lock.newCondition();//同步监视器 Condition condition02 = lock.newCondition(); Condition condition03 = lock.newCondition(); private int num = 1;//1A 2B 3C public void printA() { lock.lock(); try {//业务代码->判断->执行->通知 while(num != 1) { //等待 condition01.await(); } System.out.println(Thread.currentThread().getName()+"AA"); //唤醒指定的线程(B) num = 2; condition02.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printB() { lock.lock(); try {//业务代码->判断->执行->通知 while(num != 2) { condition02.await(); } System.out.println(Thread.currentThread().getName()+"BB"); num = 3; condition03.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printC() { lock.lock(); try {//业务代码->判断->执行->通知 while (num != 3) { condition03.await(); } System.out.println(Thread.currentThread().getName()+"CC"); num = 1; condition01.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }