Знакомство со спин-блокировками, написание от руки простой спин-блокировки

задняя часть

1. Введение

Спин-блокировка реализована за счет того, что текущий поток может непрерывно выполняться в теле цикла. Когда состояние цикла изменяется другими потоками, он может войти в критическую секцию, и процесс потока, пытающегося получить блокировку, не будет блокировать;

2. Анализ

1. Преимущества

  1. Спин-блокировка не приведет к переключению состояния потока, она всегда будет в пользовательском состоянии, то есть поток всегда активен; она не приведет к переходу потока в состояние блокировки, уменьшая ненужное переключение контекста и выполнение скорость быстрая
  2. Блокировка без вращения перейдет в состояние блокировки, когда блокировка не может быть получена, тем самым входя в состояние ядра.Когда блокировка получена, ее необходимо восстановить из состояния ядра, и требуется переключение контекста потока. (После того, как поток заблокирован, он переходит в состояние планирования ядра (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);
   }
}