原来提到的比较并交换(CAS),底层使用的就是自旋,自旋就是多次尝试,多次访问,不会阻塞的状态就是自旋。
自旋锁:spinlock,是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁
自旋锁的优缺点:
好处:减少线程上下文切换的消耗, 循环比较获取直到成功为止,没有类似于wait的阻塞
缺点:循环会消耗CPU, 当不断自旋的线程越来越多的时候,会因为执行while循环不断的消耗CPU资源
package com.youliao.thread;
import com.youliao.java.SingletonDemo;
import java.security.PublicKey;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @Author Dali
* @Date 2021/5/23 13:50
* @Version 1.0
* @Description :自旋锁代码SpinLockDemo
*/
public class SpinLockDemo {
//原子引用线程
AtomicReference<Thread> atomicReference = new AtomicReference<>();
/**
* 上锁
*/
public void myLock() {
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "\t come in (~ ̄▽ ̄)~");
// 开始自旋,期望值是null,更新值是当前线程,如果是null,则更新为当前线程,否者自旋
while (!atomicReference.compareAndSet(null, thread)) {
}
}
/**
* 解锁
*/
public void myUnlock() {
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread, null);
System.out.println(Thread.currentThread().getName() + "\t invoked myUnlock()");
}
public static void main(String[] args) {
SpinLockDemo spinLockDemo = new SpinLockDemo();
new Thread(() -> {
spinLockDemo.myLock();
//暂停5秒中
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLockDemo.myUnlock();
}, "AA").start();
//暂停1秒中 让AA线程运行完
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();
}
}
运行结果: