模拟问题
package com.zhong.thread.usethread;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName : ThreadProject
* @Description : 线程安全问题小案例
* @Author : zhx
* @Date: 2024-02-19 13:21
*/
public class ThreadProject {
public static void main(String[] args) {
// 创建账户对象 代表共享账户
Account acc = new Account("WPPZHX-999999999", 100);
// 创建两个线程 代表两个用户 去同一个账户对象取钱 100
new DrawThread(acc, "小王").start(); // 小王
new DrawThread(acc, "小钟").start(); // 小钟
}
}
class DrawThread extends Thread {
private Account acc;
public DrawThread(Account acc, String name) {
super(name);
this.acc = acc;
}
@Override
public void run() {
// 小王 小钟 各自取 100元
acc.drawMoney(100);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Account {
private String cardID;
private double money;
public void drawMoney(double getMoney) {
// 获取当前取钱对象名字
String name = Thread.currentThread().getName();
if (this.money >= getMoney) {
System.out.println(name + " 取钱 " + money);
money -= getMoney;
System.out.println(name + " 取钱后余额还剩 " + money);
} else {
System.out.println(name + " 取钱 余额不足......");
}
}
}
解决问题
- synchronized() 快捷使用 选中要加锁的代码块 Ctrl + Alt + T 选择第 9 个
- 静态方法使用锁的时候建议使用 Account.class 作为公共资源
package com.zhong.thread.usethread;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName : ThreadProject
* @Description : 线程安全问题小案例
* @Author : zhx
* @Date: 2024-02-19 13:21
*/
public class ThreadProject {
public static void main(String[] args) {
// 创建账户对象 代表共享账户
Account acc = new Account("WPPZHX-999999999", 100);
// 创建两个线程 代表两个用户 去同一个账户对象取钱 100
new DrawThread(acc, "小王").start(); // 小王
new DrawThread(acc, "小钟").start(); // 小钟
}
}
class DrawThread extends Thread {
private Account acc;
public DrawThread(Account acc, String name) {
super(name);
this.acc = acc;
}
@Override
public void run() {
// 小王 小钟 各自取 100 元
acc.drawMoney(100);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Account {
private String cardID;
private double money;
public static void test() {
// 静态方法使用锁的时候建议使用 Account.class 作为公共资源
synchronized (Account.class){
}
}
public void drawMoney(double getMoney) {
// 获取当前取钱对象名字
String name = Thread.currentThread().getName();
synchronized (this) {
if (this.money >= getMoney) {
System.out.println(name + " 取钱 " + money);
money -= getMoney;
System.out.println(name + " 取钱后余额还剩 " + money);
} else {
System.out.println(name + " 取钱 余额不足......" + money);
}
}
}
}
package com.zhong.thread.usethread;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @ClassName : ThreadProject
* @Description : 线程安全问题小案例
* @Author : zhx
* @Date: 2024-02-19 13:21
*/
public class ThreadProject {
public static void main(String[] args) {
// 创建账户对象 代表共享账户
Account acc = new Account("WPPZHX-999999999", 100);
// 创建两个线程 代表两个用户 去同一个账户对象取钱 100
new DrawThread(acc, "小王").start(); // 小王
new DrawThread(acc, "小钟").start(); // 小钟
}
}
class DrawThread extends Thread {
private Account acc;
public DrawThread(Account acc, String name) {
super(name);
this.acc = acc;
}
@Override
public void run() {
// 小王 小钟 各自取 100 元
acc.drawMoney(100);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Account {
private String cardID;
private double money;
public static void test() {
// 静态方法使用锁的时候建议使用 Account.class 作为公共资源
synchronized (Account.class) {
}
}
// synchronized 直接给方法上锁
public synchronized void drawMoney(double getMoney) {
// 获取当前取钱对象名字
String name = Thread.currentThread().getName();
if (this.money >= getMoney) {
System.out.println(name + " 取钱 " + money);
money -= getMoney;
System.out.println(name + " 取钱后余额还剩 " + money);
} else {
System.out.println(name + " 取钱 余额不足......" + money);
}
}
}
package com.zhong.thread.usethread;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @ClassName : ThreadProject
* @Description : 线程安全问题小案例
* @Author : zhx
* @Date: 2024-02-19 13:21
*/
public class ThreadProject {
public static void main(String[] args) {
// 创建账户对象 代表共享账户
Account acc = new Account("WPPZHX-999999999", 100);
// 创建两个线程 代表两个用户 去同一个账户对象取钱 100
new DrawThread(acc, "小王").start(); // 小王
new DrawThread(acc, "小钟").start(); // 小钟
}
}
class DrawThread extends Thread {
private Account acc;
public DrawThread(Account acc, String name) {
super(name);
this.acc = acc;
}
@Override
public void run() {
// 小王 小钟 各自取 100 元
acc.drawMoney(100);
}
}
@Data
@NoArgsConstructor
class Account {
private String cardID;
private double money;
private final Lock lock = new ReentrantLock();
public Account(String cardID, double money) {
this.cardID = cardID;
this.money = money;
}
public static void test() {
// 静态方法使用锁的时候建议使用 Account.class 作为公共资源
synchronized (Account.class) {
}
}
public void drawMoney(double getMoney) {
// 获取当前取钱对象名字
String name = Thread.currentThread().getName();
// 上锁
lock.lock();
try { // 即使中间程序出错 也不影响锁
if (this.money >= getMoney) {
System.out.println(name + " 取钱 " + money);
money -= getMoney;
System.out.println(name + " 取钱后余额还剩 " + money);
} else {
System.out.println(name + " 取钱 余额不足......" + money);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 解锁
lock.unlock();
}
}
}