- ReentrantLock、AQS权威解析,看懂彻底明白ReentrantLock底层原理
- 1、代码清晰简洁,深入理解AQS锁
- 2、不支持锁重入,只是让人理解底层原因
- 3、全面掌握CAS的使用
package com.acwer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
public class MiniAQSLock {
static int count=0;
public static void main(String[] args) {
MiniAQSLock lock=new MiniAQSLock();
List<Thread> threads=new ArrayList<>();
for (int i = 0; i < 100; i++) {
Thread thread = new Thread(() -> {
sleep();
lock.lock();
sleep();
count++;
lock.unlock();
});
threads.add(thread);
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
}catch (Exception ex){}
}
System.out.println(count);
}
static void sleep(){
Random r=new Random();
try{
Thread.sleep(r.nextInt(10));
}catch (Exception ex){}
}
private AtomicBoolean busy=new AtomicBoolean(false);
public void lock(){
if(!tryLock()){
queenHold(addWaiter(new Node(Thread.currentThread())));
}
}
private boolean tryLock(){
return busy.compareAndSet(false,true);
}
private boolean shouldPark(Node p){
AtomicBoolean waitStatus = p.waitStatus;
boolean b = waitStatus.get();
if(b){
return true;
}
waitStatus.compareAndSet(b,true);
return false;
}
private void unpark(Node p){
AtomicBoolean waitStatus = p.waitStatus;
boolean ws = waitStatus.get();
if(ws){
waitStatus.compareAndSet(ws,false);
}
Node s = p.next;
if(s!=null){
LockSupport.unpark(s.thread);
}
}
private void queenHold(Node node){
for (;;){
Node pre = node.pre;
if(pre==head&&tryLock()){
pre.next=null;
head=node;
return;
}
if(shouldPark(pre)){
LockSupport.park(this);
}
}
}
public void unlock(){
busy.set(false);
unpark(head);
}
private Node addWaiter(Node node){
for (;;){
Node tail= holdTail.get();
node.pre=tail;
if(holdTail.compareAndSet(tail,node)){
tail.next=node;
break;
}
}
return node;
}
private Node head=new Node();
private AtomicReference<Node> holdTail=new AtomicReference<>(head);
class Node{
public volatile Thread thread;
public volatile Node pre;
public volatile Node next;
public AtomicBoolean waitStatus=new AtomicBoolean(false);
public Node(){}
public Node(Thread t){
this.thread=t;
}
}
}