自旋锁(spinlock):是指尝试获取锁的线程不会当即阻塞,而是采用循环的方式去尝试获取锁。java
优势:循环比较获取直到成功,没有相似wait的阻塞。还能减小线程上下文切换的消耗测试
缺点:当不断自旋的线程愈来愈多的时候,会由于执行while循环不断的消耗CPU资源atom
自旋的本质就是CAS方法和while循环线程
public class SpinLockDemo { // 原子引用线程 AtomicReference<Thread> atomicReference = new AtomicReference<>(); public void myLock() { Thread thread = Thread.currentThread(); // 返回对当前正在执行的线程对象的引用 System.out.println(Thread.currentThread().getName() + "进来了"); /* 首个线程进来,发现atomicReference是null,就变为这个线程。而后取反变为false,跳出循环等待。 若是发现卫生间里面还有人,就一直循环一直等,直到卫生间里面没人。 */ while (!atomicReference.compareAndSet(null, thread)) { //没跳出就一直循环 } } public void myUnlock() { Thread thread = Thread.currentThread(); // 我出去要解锁,而后变为null给下一我的用 atomicReference.compareAndSet(thread, null); System.out.println(Thread.currentThread().getName() + "调用myUnlock方法"); }
测试code
public static void main(String[] args) throws InterruptedException { SpinLockDemo spinLockDemo = new SpinLockDemo(); // 我A线程进去占用这把锁,而后霸占5s new Thread(() -> { spinLockDemo.myLock(); TimeUnit.SECONDS.sleep(5); spinLockDemo.myUnlock(); }, "线程A").start(); // 主线程main暂停1s,保证A线程先启动 TimeUnit.SECONDS.sleep(1); // 我B线程再进去循环等待这把锁 new Thread(() -> { spinLockDemo.myLock(); spinLockDemo.myUnlock(); }, "线程B").start(); }
运行结果对象
线程A进来了 //A进来了,A要占用5s 线程B进来了 //B也进来了,发现卫生间有人,循环等待A出来 线程A调用myUnlock方法 //A出来了 线程B调用myUnlock方法 //B占用完锁,也出来了