继承AQS
public class ReentrantLockUseAQS extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0,1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if (compareAndSetState(1,0)) {
setExclusiveOwnerThread(null);
return true;
}
return false;
}
public static void main(String[] args) {
final ReentrantLockUseAQS lock = new ReentrantLockUseAQS();
new Thread(() -> {
lock.acquire(1);
System.out.println("T1成功获取锁," + LocalDateTime.now());
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("T1执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.release(1);
System.out.println("T1释放了锁," + LocalDateTime.now());
}
},"T1").start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.acquire(1);
System.out.println("T2获取到锁," + LocalDateTime.now());
lock.release(1);
},"T2").start();
}
}
用自己实现的AQS
- acquire思路:需要获取锁的线程不断去轮询获取锁,多次获取不到则放入到队尾且park,等待其他线程唤醒,被唤醒后继续去获取锁,若获取到则继续往下执行
- release思路:释放自己持有的锁,唤醒下一个线程节点去争抢锁
- 如何保证线程安全:使用Java自带的Unsafe的CAS控制
public class MyLock {
private volatile int state;
private static final Unsafe unsafe;
private static final long stateOffset;
protected transient Thread exclusiveOwnerThread;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
stateOffset = unsafe.objectFieldOffset
(MyLock.class.getDeclaredField("state"));
} catch (Exception ex) { throw new Error(ex); }
}
protected transient volatile Node head;
protected transient volatile Node tail;
class Node {
Node prev;
Node next;
Thread thread;
Node() {
}
Node(Thread thread) {
this.thread = thread;
}
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
public void acquire() {
if (!tryAcquire()) {
Node node = new Node(Thread.currentThread());
addWaiter(node);
acquireQueued(node);
}
}
protected final boolean acquireQueued(Node node) {
for (;;) {
if (node == head && tryAcquire()) {
if (head.next == null) {
head = tail = null;
} else {
head = head.next;
}
break;
} else {
System.out.println(Thread.currentThread().getName() + ",park");
LockSupport.park();
}
}
return true;
}
public void release() {
if (exclusiveOwnerThread != Thread.currentThread()) {
throw new RuntimeException("当前线程没有占有锁,无法释放锁");
}
if (compareAndSetState(1,0)) {
exclusiveOwnerThread = null;
}
if (head != null) {
System.out.println("释放锁时,UnPark线程:" + head.thread.getName());
LockSupport.unpark(head.thread);
}
}
protected boolean tryAcquire() {
final Thread current = Thread.currentThread();
if (state == 0) {
if (compareAndSetState(0, 1)) {
exclusiveOwnerThread = current;
return true;
}
}
return false;
}
protected Node addWaiter(Node node) {
if (tail != null) {
tail.next = node;
node.prev = tail;
tail = node;
} else {
head = tail = node;
}
System.out.println(Thread.currentThread().getName() + "进入同步队列");
return node;
}
public static void main(String[] args) {
final MyLock myLock = new MyLock();
Runnable task1 = () -> {
myLock.acquire();
System.out.println(Thread.currentThread().getName() + "获取了锁," + LocalDateTime.now());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
myLock.release();
};
Runnable task2 = () -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
myLock.acquire();
System.out.println(Thread.currentThread().getName() + "获取了锁," + LocalDateTime.now());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
myLock.release();
};
Runnable task3 = () -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
myLock.acquire();
System.out.println(Thread.currentThread().getName() + "获取了锁," + LocalDateTime.now());
myLock.release();
};
new Thread(task1,"T1").start();
new Thread(task2,"T2").start();
new Thread(task3,"T3").start();
}
}
await、signal
public class MyCondition extends MyLock{
private transient Node firstWaiter;
private transient Node lastWaiter;
public void await() throws InterruptedException {
final Thread currentThread = Thread.currentThread();
if (exclusiveOwnerThread != currentThread) {
throw new RuntimeException("当前线程没持有锁");
}
final Node node = new Node(currentThread);
if (compareAndSetState(1,0)) {
exclusiveOwnerThread = null;
addConditionWaiter(node);
LockSupport.unpark(head.thread);
LockSupport.park();
System.out.println(Thread.currentThread().getName() + "被UNPark,重新acquire");
acquireQueued(node);
}
}
public void signal() {
addWaiter(firstWaiter);
LockSupport.unpark(firstWaiter.thread);
}
private Node addConditionWaiter(Node node) {
if (lastWaiter != null) {
lastWaiter.next = node;
node.prev = lastWaiter;
lastWaiter = node;
} else {
firstWaiter = lastWaiter = node;
}
System.out.println(Thread.currentThread().getName() + ",addConditionWaiter");
return node;
}
public static void main(String[] args) {
MyCondition myLock = new MyCondition();
new Thread(() -> {
myLock.acquire();
System.out.println("T1获取了锁" + LocalDateTime.now());
try {
System.out.println("T1 await让出了锁" + LocalDateTime.now());
myLock.await();
System.out.println("T1 await结束被signal" + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
myLock.release();
System.out.println("T1释放了锁");
},"T1").start();
new Thread(() -> {
myLock.acquire();
System.out.println("T2获取了锁" + LocalDateTime.now());
myLock.signal();
System.out.println("T2 signal其他线程");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T2休眠三秒后再释放锁");
myLock.release();
},"T2").start();
}
}