线程安全的本质是正确性,而正确性的含义是程序按照预期执行java
理论上线程安全的程序,应该要避免出现可见性问题(CPU缓存)、原子性问题(线程切换)和有序性问题(编译优化)算法
须要分析是否存在线程安全问题的场景:存在共享数据且数据会发生变化,即有多个线程会同时读写同一个数据缓存
数据竞争(Data Race):多个线程同时访问同一数据,而且至少有一个线程会写这个数据安全
1. addbash
private static final int MAX_COUNT = 1_000_000;
private long count = 0;
// 非线程安全
public void add() {
int index = 0;
while (++index < MAX_COUNT) {
count += 1;
}
}复制代码
2. add + synchronized数据结构
private static final int MAX_COUNT = 1_000_000;
private long count = 0;
public synchronized long getCount() {
return count;
}
public synchronized void setCount(long count) {
this.count = count;
}
// 非线程安全
public void add() {
int index = 0;
while (++index < MAX_COUNT) {
setCount(getCount() + 1);
}
}复制代码
1. 转帐多线程
public class Account {
private int balance;
// 非线程安全,存在竟态条件,可能会超额转出
public void transfer(Account target, int amt) {
if (balance > amt) {
balance -= amt;
target.balance += amt;
}
}
}复制代码
面对数据竞争和竟态条件问题,能够经过互斥的方案来实现线程安全,互斥的方案能够统一归为锁并发
活跃性问题:某个操做没法执行下去,包括三种状况:死锁、活锁、饥饿分布式
喜欢的能够关注个人公众号,java小瓜哥的分享平台,平时整理的资料都放在里面了性能