以下以两人共用一个银行卡账户的方式,同时取钱,两条线程同时执行,为了保证线程安全,我们对关键的部分进行加锁的三种方式
线程类
public class DrawThread extends Thread {
private Account acc;
public DrawThread(Account acc, String name){
super(name);
this.acc=acc;
}
@Override
public void run(){
//取钱 //每个线程在start的时候 都会执行 这个run方法
acc.drawMoney(10000);
}
}
账户类
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Account {
private String cardId;
private double money;
//创建一个锁对象
private final Lock lk =new ReentrantLock(); //手动锁
public Account() {
}
public Account(String cardId, double money) {
this.cardId = cardId;
this.money = money;
}
//静态代码 用class作为锁
public static void test(){
synchronized (Account.class){
}
}
//取钱的方法
//同步代码块上锁
/** public void drawMoney(double money){
//谁来取钱?
String name = Thread.currentThread().getName();
//判断余额是否足够
synchronized (this){ //this 在这个过程中是共同拥有的相同的数据 所以能锁住
if(this.money>=money){
System.out.println(name+"取钱"+money+"成功!");
this.money -= money;
System.out.println(name+"取钱后,剩余"+this.money);
}else {
System.out.println(name+"余额不足");
}
}
}
*/
//取钱方法
//同步方法上锁
/** public synchronized void drawMoney(double money){
//谁来取钱?
String name = Thread.currentThread().getName();
//判断余额是否足够
if(this.money>=money){
System.out.println(name+"取钱"+money+"成功!");
this.money -= money;
System.out.println(name+"取钱后,剩余"+this.money);
}else {
System.out.println(name+"余额不足");
}
}
*/
//取钱的方法
//手动锁
public synchronized void drawMoney(double money){
//谁来取钱?
String name = Thread.currentThread().getName();
lk.lock(); //加锁
//判断余额是否足够
if(this.money>=money){
System.out.println(name+"取钱"+money+"成功!");
this.money -= money;
System.out.println(name+"取钱后,剩余"+this.money);
}else {
System.out.println(name+"余额不足");
}
lk.unlock(); //解锁
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
执行
public class ThreadTest {
public static void main(String[] args) {
//创建一个账户
Account acc = new Account("ic000",10000);
//创建两个线程分别代表小明和小红 同时 在这个个账户中取钱
new DrawThread(acc,"小明").start();
new DrawThread(acc,"小红").start();
Account acc2 = new Account("ic002",10000);
//创建两个线程分别代表小明和小红 同时 在这个个账户中取钱
new DrawThread(acc2,"小黑").start();
new DrawThread(acc2,"小白").start();
}
}
效果: