1、CAS无锁机制原理(无锁指不是竞争去抢)
1)定义一个锁的状态
2)状态值=0,则表示没有线程获取到该锁
3)状态值=1,则表示有线程已经持有该锁
实现细节:
2、CAS获取锁的流程:
将该锁的状态从0改为1
能够修改成功,则表示获取锁成功
如果获取锁失败,则不会阻塞而是通过循环(自旋来控制重试)
3、CAS释放锁的流程:
将该锁的状态从1改为0
如果能够修改成功,则表示释放锁成功
4、如果一直获取锁失败,一直在做自旋,非常消耗cpu资源
所以要给它做个次数限制,最多自旋10次
5、在包com.study.base.util下,添加AtomicTryLock.java
package com.study.base.util;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
/**
* 利用cas手写一把锁
*
* @author User
*
*/
public class AtomicTryLock {
/**
* 0--表示没有人获取该锁 1--表示该锁已经被线程持有了
*/
private AtomicInteger cas = new AtomicInteger(0);
/**
* 记录这把锁当前是被哪个线程所持有的
*/
private Thread lockCurrentThread;
/**
* 计数器实现可重入功能
*/
private int count;
/**
* 获取锁
* 获取成功返回true,cas从0变为1,获取失败返回false,cas更新失败
*
* @return
*/
public boolean tryLock() {
boolean result;
// 如果当前线程已经获取到了锁,线程数增加一,然后返回
if (lockCurrentThread == Thread.currentThread()) {
count++;
return true;
}
// 通过自旋不断重试
while (true) {
result = cas.compareAndSet(0, 1);
if (result) {
lockCurrentThread = Thread.currentThread();
return result;
}else {
System.out.println(Thread.currentThread().getName() + ", 重试");
}
//释放cpu资源,避免cpu飙高
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}
/**
* 释放锁
*
* @return
*/
public boolean unLock() {
// 锁必须要当前拿到锁的线程来释放
if (lockCurrentThread != Thread.currentThread()) {
return false;
}
if (count > 0) {// 如果大于0,表示当前线程多次获取了该锁,释放锁通过count减一来模拟
count--;
return true;
} else {
return cas.compareAndSet(1, 0);
}
}
public static void main(String[] args) {
AtomicTryLock atomicTryLock = new AtomicTryLock();
IntStream.range(1, 10).forEach((i) -> new Thread(() -> {
try {
boolean result = atomicTryLock.tryLock();
if (result) {
atomicTryLock.lockCurrentThread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + ",获取锁成功!");
} else {
System.out.println(Thread.currentThread().getName() + ",获取锁失败!");
}
} catch (Exception e) {
} finally {
if (atomicTryLock != null) {
Boolean b = atomicTryLock.unLock();
if (b) {
System.out.println(Thread.currentThread().getName() + ",释放锁成功!");
}
}
}
}).start());
}
}
6、执行结果
Thread-0,获取锁成功!
Thread-6, 重试
Thread-6, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-4, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-2, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-3, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-0,释放锁成功!
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-6, 重试
Thread-6, 重试
Thread-6, 重试
Thread-6, 重试
Thread-6, 重试
Thread-8,获取锁成功!
Thread-8,释放锁成功!
Thread-6, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-2, 重试
Thread-1, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-5, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-6,获取锁成功!
Thread-6,释放锁成功!
Thread-7, 重试
Thread-7,获取锁成功!
Thread-7,释放锁成功!
Thread-5, 重试
Thread-5,获取锁成功!
Thread-5,释放锁成功!
Thread-3, 重试
Thread-3,获取锁成功!
Thread-3,释放锁成功!
Thread-4, 重试
Thread-4,获取锁成功!
Thread-4,释放锁成功!
Thread-2, 重试
Thread-2,获取锁成功!
Thread-2,释放锁成功!
Thread-1, 重试
Thread-1,获取锁成功!
Thread-1,释放锁成功!
可以看到同一时间只有一个线程获取锁。
参考资料:
https://blog.csdn.net/fuyuwei2015/article/details/83387536
注:最新代码上传至https://github.com/csj50/webapp2.git