【线程安全】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() {
@Override
public void run() {
for (int i = 1; i <= 40; i++) {
ticket.saleTicket();
}
}
}, "售票员1").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 40; i++) {
ticket.saleTicket();
}
}
}, "售票员2").start();
new Thread(new Runnable() {
@Override
public 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() {
@Override
public void run() {
for (int i = 1; i <= 40; i++) {
ticket.saleTicket();
}
}
}, "售票员1").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 40; i++) {
ticket.saleTicket();
}
}
}, "售票员2").start();
new Thread(new Runnable() {
@Override
public 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();
}
}
}
运行结果: