10.Java锁之自旋锁
Posted 为什么算法这么难
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.Java锁之自旋锁相关的知识,希望对你有一定的参考价值。
概念
自旋锁(spinlock):是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁。
- 之前学过的CAS,底层使用的就是自旋锁,自旋就是多次尝试,多次访问,不会阻塞的状态就是自旋。
优缺点
优点:循环比较获取直到成功,没有类似wait的阻塞。还能减少线程上下文切换的消耗
缺点:当不断自旋的线程越来越多的时候,会因为执行while循环不断的消耗CPU资源
手写自旋锁
自旋的本质就是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方法");
}
测试
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占用完锁,也出来了
以上是关于10.Java锁之自旋锁的主要内容,如果未能解决你的问题,请参考以下文章