1. Введение
Спин-блокировка реализована за счет того, что текущий поток может непрерывно выполняться в теле цикла. Когда состояние цикла изменяется другими потоками, он может войти в критическую секцию, и процесс потока, пытающегося получить блокировку, не будет блокировать;
2. Анализ
1. Преимущества
- Спин-блокировка не приведет к переключению состояния потока, она всегда будет в пользовательском состоянии, то есть поток всегда активен; она не приведет к переходу потока в состояние блокировки, уменьшая ненужное переключение контекста и выполнение скорость быстрая
- Блокировка без вращения перейдет в состояние блокировки, когда блокировка не может быть получена, тем самым входя в состояние ядра.Когда блокировка получена, ее необходимо восстановить из состояния ядра, и требуется переключение контекста потока. (После того, как поток заблокирован, он переходит в состояние планирования ядра (Linux), что заставит систему переключаться между пользовательским режимом и режимом ядра, серьезно влияя на производительность блокировки)
2. Проблемы
1. Если поток удерживает блокировку слишком долго, это приведет к тому, что другие потоки, ожидающие получения блокировки, войдут в цикл ожидания, потребляя ресурсы ЦП. Неправильное использование может привести к чрезвычайно высокой загрузке ЦП.
2. Это может привести к «голоданию нитей»;
3. Написание спин-блокировки JAVA от руки легко понять
package com.xxx.lcloud.study;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* Created by hinson on 2020-5-19.
*/
public class SpinLock {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
public static void main(String[] args) {
SpinLock spinLock = new SpinLock();
new Thread(()->{
spinLock.lock();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.unLock();
},"线程A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
spinLock.lock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.unLock();
},"线程B").start();
}
private void lock(){
Thread thread = Thread.currentThread();
//准备抢占
while(!atomicReference.compareAndSet(null,thread)){
//空轮询
}
}
private void unLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread,null);
}
}