自旋锁是什么?
spinlock,不断的自旋(自我循环)尝试获得锁。
参考文档:Java中的自旋锁
自旋锁的实现
import java.util.concurrent.atomic.AtomicReference;
public class SpinLockTest {
private AtomicReference<Thread> cas = new AtomicReference<>();
public void lock() throws InterruptedException {
Thread current = Thread.currentThread();
//如果没获得锁,则打印日志自旋
while (!cas.compareAndSet(null, current)) {
System.out.println("did not get the lock 1s");
}
}
public void unlock() {
Thread current = Thread.currentThread();
cas.compareAndSet(current, null);
}
public static void main(String[] args) {
SpinLockTest a = new SpinLockTest();
Thread ra = new Thread(new Runnable() {
@Override
public void run() {
try {
a.lock();
Thread.sleep(1000);
a.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread rb = new Thread(new Runnable() {
@Override
public void run() {
try {
a.lock();
a.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
ra.start();
rb.start();
}
}
自旋锁的实现方式有很多,通过各种锁的方式都可以实现,思想上让一个线程在没获得锁的前提下,不断循环即可
为什么要用自旋锁
一开始被问到,为什么要用自旋锁,有点儿懵。
自旋锁,我们知道是为了实现一个阻塞不断尝试的效果。但是阻塞是有很多方法的,为什么不通过挂起再唤醒呢?
- 自旋锁的缺点
自旋锁,由于一直在尝试,所以肯定会消耗cpu资源,特别是当一个线程持有锁时间过长时,可能会导致cpu使用率极高
java 的自旋锁是公平的吗?他不是公平的,它无法保持等待时间最长的锁可以先获得锁,因此存在着“线程饥饿”的问题
自旋锁的优点
自旋锁最大的优点就是线程一直是active的,它减少了不必要的上下文切换,执行速度快。
在一般的wait,notify方式中,线程会进入block状态
它代表着,线程从用户态进入了内核态
当获得锁时,会需要从内核态中恢复,状态的切换会影响锁的性能
自旋锁的扩展
1.通过计数的方式,增加可重入锁
2.通过递增序列号完成公平锁
3.通过链表,CLHLock实现共性能,公平的自旋锁,不断轮询前驱服务