文章目录
并发编程-原子性保证
一、前言
关于并发编程的三大问题:原子性、有序性、可见性,我们在第一次的分享中就提到过了
今天,我们就来聊聊原子性相关的问题
这里关于显示锁 synchronized
,我就不再赘述了,感兴趣的同学,可以翻阅我之前写的介绍 synchronized 的文章哦:https://mp.weixin.qq.com/s/L7VZ1ELlWG5tHZ6hMgbGSg
那这篇文章我们还能讲什么东西呢?之前我也提过了,原子性问题,我们要关注的不是原子性如何实现,而是怎么确保锁的效率和避免死锁
二、限定锁的范围
虽然我们前面提到,我们需要注意的问题,是确保锁的效率和避免死锁,但是我还是想提一下锁范围这个问题
在讲这个问题之前,我想先引出我会在全篇使用的一个例子,那就是银行转账
public class Account {
private long balance;
private String bankID;
public Account(String bankID) {
this.bankID = bankID;
}
// 转账方法
// 注:目前这个状态是不具备一点线程安全性的
public boolean transfer(String targetID,long amount) {
if (this.balance<amount) return false;
this.balance-=amount;
// 将要为被转用户设置的新 balance 数
long balanceToBeSet = target.getBalance() + amount;
// 在转账和被转账账户之间,设置睡眠,模拟各大银行之间的转账延迟
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
target.setBalance(balanceToBeSet);
return true;
}
// getter and setter
}
Account
类包括两个成员变量,一个是表示用户的 bankID
,一个表示用户当前拥有的钱数 balance
这里我们有一个需求,就是希望账户A 转钱给账户B,账户B 转钱给 账户C
测试用例如下:
package top.faroz.back_transfer;
import java.util.HashMap;
public class TransferDemo {
public static void main(String[] args) throws InterruptedException {
Account A = new Account("A");
Account B = new Account("B");
Account C = new Account("C");
A.setBalance(200);
B.setBalance(200);
C.setBalance(200);
TransferThread t1 = new TransferThread(A, B, 100,1000);
TransferThread t2 = new TransferThread(B, C, 100,100);
t1.start();
t2.start();
t1.join();
t2.join();
System.out