可以回顾之前所说的CAS 自旋锁(spinlock)是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU 简而言之:一个线程想去获得一个资源,但是该资源暂时获取不到,该线程就会先去做其他事情,过一会再来获取这个资源
一、实现自旋
定义锁
public class SpinLockDemo {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
// 获取锁
public void myLock() {
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "--myLock,come in");
while (!atomicReference.compareAndSet(null, thread)) {
}
System.out.println(thread.getName() + "--myLock,get");
}
// 释放锁
public void myUnLock() {
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread, null);
System.out.println(thread.getName() + "--myUnLock()");
}
}
测试
public class SpinLockDemoTest {
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();
},"AA").start();
try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
new Thread(()->{
spinLockDemo.myLock();
try {TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
spinLockDemo.myUnLock();
},"BB").start();
}
}
结果
AA--myLock,come in
AA--myLock,get
BB--myLock,come in
AA--myUnLock()
BB--myLock,get
BB--myUnLock()
AA线程获取锁之后,等待5秒,在此期间BB线程想要获取锁,由于AA线程尚未释放锁,所以此时BB线程通过循环尝试获取锁。
5秒之后,AA线程释放了锁,此时BB线程拿到了锁。