自旋锁,借鉴CAS思想
是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁, 当线程发现锁被占用时,会不断循环判断锁的状态,直到获取。这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU
OpenJDK源码里面查看下Unsafe.java do while循环
自己实现一个自旋锁SpinLockDemo
package com.dongguo.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Dongguo
* @date 2021/9/7 0007-10:36
* 题目:实现一个自旋锁
* 自旋锁好处:循环比较获取没有类似wait的阻塞。
*
* 通过CAS操作完成自旋锁,A线程先进来调用myLock方法自己持有锁5秒钟,B随后进来后发现
* 当前有线程持有锁,不是null,所以只能通过自旋等待,直到A释放锁后B随后抢到。
*/
public class SpinLockDemo {
AtomicReference atomicReference = new AtomicReference();
public void MyLock() {
System.out.println(Thread.currentThread().getName() + " come in ");
//修改不成功
while (!atomicReference.compareAndSet(null, Thread.currentThread())) {
//循环等待(自旋)
}
//修改成功
System.out.println(Thread.currentThread().getName() + "加锁成功");
}
public void MyUnLock() {
atomicReference.compareAndSet(Thread.currentThread(), null);
System.out.println(Thread.currentThread().getName() + "释放锁成功");
}
public static void main(String[] args) {
SpinLockDemo spinLockDemo = new SpinLockDemo();
new Thread(() -> {
spinLockDemo.MyLock();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLockDemo.MyUnLock();
}, "t1").start();
//暂停一会儿线程,保证A线程先于B线程启动并完成
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
spinLockDemo.MyLock();
spinLockDemo.MyUnLock();
}, "t2").start();
}
}
运行结果
t1 come in
t1加锁成功
t2 come in
t1释放锁成功
t2加锁成功
t2释放锁成功