多线程教程(二十三) 无锁实现线程安全
题目描述:
总额10000元,1000个人取钱,每人取10块,取完余额刚好为0.
加锁方法
class AccountUnsafe implements Account {
private Integer balance;
public AccountUnsafe(Integer balance) {
this.balance = balance;
}
@Override
public synchronized Integer getBalance() {
return balance;
}
@Override
public synchronized void withdraw(Integer amount) {
balance -= amount;
}
}
结果为:
0 cost: 399 ms
无锁解决方案
class AccountSafe implements Account {
private AtomicInteger balance;
public AccountSafe(Integer balance) {
this.balance = new AtomicInteger(balance);
}
@Override
public Integer getBalance() {
return balance.get();
}
@Override
public void withdraw(Integer amount) {
while (true) {
int prev = balance.get();
int next = prev - amount;
if (balance.compareAndSet(prev, next)) {
break;
}
}
// 可以简化为下面的方法
// balance.addAndGet(-1 * amount);
}
}
执行测试代码
public static void main(String[] args) {
Account.demo(new AccountSafe(10000));
}
某次的执行结果
0 cost: 302 ms
实际上无锁的解决方案就是使用cas,在进行赋值之前对线程内部变量和主线程的变量进行比较,当相同时进行赋值,避免锁的使用
不过这种方案适合线程数量较少的情况,因为线程多了之后cas会一直不成功,降低性能。