可以回顾之前所说的CAS 自旋锁(spinlock)是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU 简而言之:一个线程想去获得一个资源,但是该资源暂时获取不到,该线程就会先去做其他事情,过一会再来获取这个资源

一、实现自旋

定义锁

  1. public class SpinLockDemo {
  2. AtomicReference<Thread> atomicReference = new AtomicReference<>();
  3. // 获取锁
  4. public void myLock() {
  5. Thread thread = Thread.currentThread();
  6. System.out.println(thread.getName() + "--myLock,come in");
  7. while (!atomicReference.compareAndSet(null, thread)) {
  8. }
  9. System.out.println(thread.getName() + "--myLock,get");
  10. }
  11. // 释放锁
  12. public void myUnLock() {
  13. Thread thread = Thread.currentThread();
  14. atomicReference.compareAndSet(thread, null);
  15. System.out.println(thread.getName() + "--myUnLock()");
  16. }
  17. }

测试

  1. public class SpinLockDemoTest {
  2. public static void main(String[] args) {
  3. SpinLockDemo spinLockDemo = new SpinLockDemo();
  4. new Thread(()->{
  5. spinLockDemo.myLock();
  6. try {TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace();}
  7. spinLockDemo.myUnLock();
  8. },"AA").start();
  9. try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
  10. new Thread(()->{
  11. spinLockDemo.myLock();
  12. try {TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
  13. spinLockDemo.myUnLock();
  14. },"BB").start();
  15. }
  16. }
  17. 结果
  18. AA--myLock,come in
  19. AA--myLock,get
  20. BB--myLock,come in
  21. AA--myUnLock()
  22. BB--myLock,get
  23. BB--myUnLock()

AA线程获取锁之后,等待5秒,在此期间BB线程想要获取锁,由于AA线程尚未释放锁,所以此时BB线程通过循环尝试获取锁。
5秒之后,AA线程释放了锁,此时BB线程拿到了锁。