无锁并发
电子书:
接口里面是可以有静态方法的:https://blog.csdn.net/VoiceKing2017/article/details/105087060/
------------06--01-02---------------
代码:
完整的代码:
package cn.itcast.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class TestAccount {
public static void main(String[] args) {
Account account = new AccountCas(10000);
Account.demo(account);
}
}
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)) {
break;
}
}*/
balance.getAndAdd(-1 * amount);
}
}
class AccountUnsafe implements Account {
private Integer balance;
public AccountUnsafe(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;
}
}
}
interface Account {
// 获取余额
Integer getBalance();
// 取款
void withdraw(Integer amount);
/**
* 方法内会启动 1000 个线程,每个线程做 -10 元 的操作
* 如果初始余额为 10000 那么正确的结果应当是 0
*/
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_000 + " ms");
}
}
两个线程去取款,
实现方式1加synchronized:
---
-----------------06 03------------------
实现方式2无锁实现:
我们用JDK给我们实现的一个cas来实现这个cas的锁。
无锁我们去减去账户的余额。
获取余额:
改变余额:
先用AtomicInteger获取最新的值,然后再更改值,更改之后再cas判断是不是没被更改过。
cas就是配合while使用的。
-----------06---004----------
cas于volatile的关系。
cas是如何工作的呢?
什么是当前的值,就是主存上面的值。
compareAndSet的方法内部是原子的。
用一个图理解下compareAndSet是如何工作的。
修改是有条件的,就是pre参数和主存上最新值做对比。
-----------06---005---------------
cas是原子的。
代码:
慢动作分析,可以修改值,模仿其他的线程
我改下这个。
-------------------------06-- 006 ----------------
cas于volatile的关系。
具体的数值是在哪里保存的
数字是value,用volatile修饰的。volatile是保证的最新的。
是volatile的,这要注意了,就是锁,使缓存失效。
-----------06----006-------------
cas效率?
-----------06----7-------------
线程数少于cpu核心用cas。
cas的线程不要多于cpu的核心数。
cas是乐观锁。
-----------06----8--------------