本文简单介绍下自旋锁的阻塞锁,主要详细介绍自旋锁的概念、使用场景和简易代码实现。
概述
我们都知道CPU唤醒或者阻塞线程时,是有上下文切换的开销,若临界区的范围不是很大,在多核处理器中使用自旋锁是ok的。
自旋锁:采用CAS的方法,不停的去尝试获取,直到获取成功
缺点
若临界区很耗时,使用自旋锁随着时间的推移会有很多的性能问题
优点
在一定程度上,自旋可以提供效率,JDK中的atomic采用了自旋锁。
代码示例
下文通过代码去演示自旋锁的实现,采用CAS,while循环去实现。如下所示。
package com.yang.lock; import java.util.concurrent.atomic.AtomicReference; /** * 本实例演示下线程的自旋锁的实现 */ public class SpinLockDemo { private static AtomicReference<Thread> atomicReference=new AtomicReference<>(); public void lock(){ Thread thread=Thread.currentThread(); while(!atomicReference.compareAndSet(null,thread)){ System.out.println(thread.getName()+"自旋锁获取失败,重新获取中"); } } public void unlock(){ Thread thread=Thread.currentThread(); atomicReference.compareAndSet(thread,null); } public static void main(String[] args) { SpinLockDemo spinLockDemo=new SpinLockDemo(); new Thread(() -> { System.out.println(Thread.currentThread().getName()+"尝试获取自旋锁"); spinLockDemo.lock(); System.out.println(Thread.currentThread().getName()+"获取自旋锁成功"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } spinLockDemo.unlock(); System.out.println(Thread.currentThread().getName()+"释放自旋锁"); }).start(); new Thread(() -> { System.out.println(Thread.currentThread().getName()+"尝试获取自旋锁"); spinLockDemo.lock(); System.out.println(Thread.currentThread().getName()+"获取自旋锁成功"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } spinLockDemo.unlock(); System.out.println(Thread.currentThread().getName()+"释放自旋锁"); }).start(); } }
部分运行结果如下所示
Thread-0尝试获取自旋锁 Thread-0获取自旋锁成功 Thread-1尝试获取自旋锁 Thread-1自旋锁获取失败,重新获取中 Thread-1自旋锁获取失败,重新获取中 Thread-1自旋锁获取失败,重新获取中 Thread-1自旋锁获取失败,重新获取中