CAS问题
1、共享资源的访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public interface Account {
Integer getBalance();
void withDraw(Integer amount);
static void demo(Account account){ List<Thread> ts = new ArrayList<>();
for (int i = 0; i < 1000; i++) { ts.add(new Thread(() -> { account.withDraw(10); })); }
long start = System.nanoTime(); ts.forEach(Thread::start); ts.forEach(t -> { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } });
long end = System.nanoTime(); System.out.println("余额还有:" + account.getBalance() + " cost:" + (end-start)/1000_100 + " ms"); } }
|
1、加锁:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class AccountSafe implements Account{ private Integer balance; public AccountSafe(Integer balance) { this.balance = balance; } @Override public Integer getBalance() { synchronized (this){ return this.balance; } } @Override public void withDraw(Integer amount) { synchronized (this){ this.balance -= amount; } } }
public class DemoSynchronized {
public static void main(String[] args) { Account accountSafe = new AccountSafe(10000); Account.demo(accountSafe); } }
|

2、 CAS(无锁)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class AccountCAS implements Account{
private AtomicInteger balance; public AccountCAS(int 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) == true){ break; }
} } } public class DemoCAS { public static void main(String[] args) { Account accountCAS = new AccountCAS(10000); Account.demo(accountCAS);
} }
|

2、CAS工作原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public void withDraw(Integer amount) { while(true){ int prev = balance.get(); int next = prev - amount;
if (balance.compareAndSet(prev, next) == true){ break; }
} }
|
通过CAS无锁的方式来保证线程安全。其中的关键是CompareAndSet,简称CAS(也可称为Compare And Swap),它是一个由底层指令实现的原子操作。
1 2 3 4 5
| 原理: 我们得到余额,计算出要修改的值。 然后我们在判断余额的最新值和余额是否一致。这一步是原子操作 如果是,返回true,并将余额改为要修改的值 如果不是,返回false,继续循环
|
CAS的工作原理:

CAS的底层实现
其实CAS的底层是lock cmpxchg指令(X86架构),在单核CPU和多核CPU下都能够保证CAS的原子性
AtomicInteger原子类
1 2 3 4 5
|
public class AtomicInteger extends Number implements java.io.Serializable { private volatile int value; }
|
==CAS必须要volatile的支持才能实现==
3、理解CAS
CAS可以无锁保证线程的安全性,但适用于线程数少,多核CPU的场景下。
- CAS是基于乐观锁的思想。最乐观的估计,不怕被其他线程修改,如果被改变了,只要重新修改值。
- synchronized是基于悲观锁的思想:最悲观的估计,要防止其他线程来改变变量。
- CAS体现的是无锁并发,无阻塞并发
- 没有使用synchronized,所以线程不会陷入阻塞
- 但如果竞争激烈,重试必然频繁发生,效率会受到影响