【线程安全】ReentrantLock和synchronized的使用示例——言简意赅
三个进货员 分别进货 500000次、50000、50000次,一共应该进来600000箱; * 笔记:如何编写企业级的多线程代码 *
固定的变成套路+模板是什么?
不加synchronized、ReentrantLock每次都会导致不一样的结果
结果:
第一次运行
第二次运行
这就是线程不安全现象;
synchronized实现: 其中应用到了Lambda表达式,表达式未简化之前样式可见上面注释代码
package com.atguigu.signcenter.util;import java.util.concurrent.locks.ReentrantLock;/*** 题目:三个进货员 分别进货 500000次、50000、50000次,一共应该进来600000箱;* 笔记:如何编写企业级的多线程代码* 固定的变成套路+模板是什么?* 1. 在高内聚低耦合的前提下,线程 操作(资源类对外暴露的调用方法) 资源类* 1.1 一言不合,先创建一个资源类*/
public class SaleTicketDemo {public static void main(String[] args) { // 主线程,一切程序的入口Ticket ticket = new Ticket();// Thread(Runnable target, String name)// 使用匿名内部类/* new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 40; i++) {ticket.saleTicket();}}}, "售票员1").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 40; i++) {ticket.saleTicket();}}}, "售票员2").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 40; i++) {ticket.saleTicket();}}}, "售票员3").start();*/// 使用lambda表达式new Thread(() -> {for (int i = 1; i <= 500000; i++) ticket.saleTicket();}, "进货员1").start();new Thread(() -> {for (int i = 1; i <= 50000; i++) ticket.saleTicket();}, "进货员2").start();new Thread(() -> {for (int i = 1; i <= 50000; i++) ticket.saleTicket();}, "进货员3").start();}}class Ticket { // 资源类private int number = 0;private ReentrantLock lock = new ReentrantLock(); // 可重入锁public synchronized void saleTicket() {try {if (number >= 0) {number++;System.out.println("进货员进一箱水果,目前一共 = " + number);}} finally {}}}
运行结果:
ReentrantLock使用
package com.atguigu.signcenter.util;import java.util.concurrent.locks.ReentrantLock;/*** 题目:三个进货员 分别进货 500000次、50000、50000次,一共应该进来600000箱;* 笔记:如何编写企业级的多线程代码* 固定的变成套路+模板是什么?* 1. 在高内聚低耦合的前提下,线程 操作(资源类对外暴露的调用方法) 资源类* 1.1 一言不合,先创建一个资源类*/
public class SaleTicketDemo {public static void main(String[] args) { // 主线程,一切程序的入口Ticket ticket = new Ticket();// Thread(Runnable target, String name)// 使用匿名内部类/* new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 40; i++) {ticket.saleTicket();}}}, "售票员1").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 40; i++) {ticket.saleTicket();}}}, "售票员2").start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 40; i++) {ticket.saleTicket();}}}, "售票员3").start();*/// 使用lambda表达式new Thread(() -> {for (int i = 1; i <= 500000; i++) ticket.saleTicket();}, "进货员1").start();new Thread(() -> {for (int i = 1; i <= 50000; i++) ticket.saleTicket();}, "进货员2").start();new Thread(() -> {for (int i = 1; i <= 50000; i++) ticket.saleTicket();}, "进货员3").start();}}class Ticket { // 资源类private int number = 0;private ReentrantLock lock = new ReentrantLock(); // 可重入锁// public synchronized void saleTicket() {public void saleTicket() {lock.lock();try {if (number >= 0) {number++;System.out.println("进货员进一箱水果,目前一共 = " + number);}} finally {lock.unlock();}}}
运行结果: