Простое понимание спин-блокировок в Java

Java

предисловие

В предыдущей статье "В этой статье досконально разбираются различные «замки», которые часто задают в интервью."Ввел различные "блокировки" в Java, которые могут немного ощущаться вокруг, я не очень разбираюсь в этих понятиях, поэтому я решил разделить это, постепенно вводя эти блокировки, дракон, затем эта статья Давайте сначала "самоблокировка " первый.

текст

Причина

В нашей программе, если есть большое количество взаимоисключающих кодов синхронизации, когда происходит высокий параллелизм, режим ядра системы должен постоянно приостанавливать и восстанавливать потоки. Частые такие операции будут влиять на параллельную производительность нашей системы, иметь некоторое влияние. В то же время умная команда разработчиков JVM также обнаружила, что временной интервал для блокировки «общих ресурсов» во время выполнения программы чрезвычайно короток.Если поток приостанавливается и возобновляется только на это время, потребляемое время может быть больше, затем «подобрал кунжут и потерял арбуз».

В многоядерной машине несколько потоков могут выполняться параллельно. Если поток, запрашивающий блокировку позже, не получит блокировку, он не приостановит поток, а продолжит занимать время выполнения процессора, и пусть текущий поток выполняет цикл занятости (операцию вращения), то есть сохраняет глядя на удерживание То ли нить замка освободила замок, то ли это легендарный спиннинговый замок.

включить блокировку

Хотя спин-блокировка была введена в JDK1.4.2, ее необходимо включить с помощью параметра «-XX:+UseSpinning». После JDK1.6 он уже включен по умолчанию. Давайте самостоятельно реализуем упрощенную версию спин-блокировки на основе CAS.


public class SimpleSpinningLock {

    /**
     * 持有锁的线程,null表示锁未被线程持有
     */
    private AtomicReference<Thread> ref = new AtomicReference<>();

    public void lock(){
        Thread currentThread = Thread.currentThread();
        while(!ref.compareAndSet(null, currentThread)){
            //当ref为null的时候compareAndSet返回true,反之为false
            //通过循环不断的自旋判断锁是否被其他线程持有
        }
    }

    public void unLock() {
        Thread cur = Thread.currentThread();
        if(ref.get() != cur){
            //exception ...
        }
        ref.set(null);
    }
}

Простая спин-блокировка реализована всего в нескольких строчках кода, давайте попробуем.

public class TestLock {

    static int count  = 0;

    public static void main(String[] args) throws InterruptedException {
       ExecutorService executorService = Executors.newFixedThreadPool(100);
       CountDownLatch countDownLatch = new CountDownLatch(100);
       SimpleSpinningLock simpleSpinningLock = new SimpleSpinningLock();
       for (int i = 0 ; i < 100 ; i++){
           executorService.execute(new Runnable() {
               @Override
               public void run() {
                   simpleSpinningLock.lock();
                   ++count;
                   simpleSpinningLock.unLock();
                   countDownLatch.countDown();
               }
           });

       }
       countDownLatch.await();
       System.out.println(count);
    }
}

// 多次执行输出均为:100 ,实现了锁的基本功能

Как видно из вышеуказанного кода, спин состоит в том, удовлетворено ли он в условиях суждения цикла, то в чем проблема? Если замок принимается длинный, ожидание спиновой резьбы также растут долго, а белые и белые отходы смачиваются. Следовательно, в JDK операция спина в 10 раз мы можем установить параметр «-xx: Preblockspin», когда значение этого параметра превышено, традиционная поток зависает будет дождаться выпуска блокировки.

Адаптивная спин-блокировка

С обновлением JDK в 1.6 появилась вещь, называемая «адаптивной блокировкой вращения». Его внешний вид делает операцию отжима более умной и уже не такой жесткой, как раньше. Так называемый «адаптивный» означает, что для одного и того же объекта блокировки время вращения потока определяется в соответствии со временем вращения и состоянием потока, который удерживал блокировку последним. Например, для объекта блокировки A, если поток только что получил блокировку путем вращения, и этот поток также выполняется, то JVM будет думать, что операция вращения также имеет высокие шансы получить блокировку, поэтому она время отжима будет относительно продолжительным. Но если операция вращения редко бывает успешной для объекта блокировки B, JVM может даже напрямую игнорировать операцию вращения. Таким образом, адаптивная спин-блокировка — это блокировка, которая является более разумной и более дружественной к нашей бизнес-эффективности.

Эпилог

Первоначально я хотел представить в статье некоторые концепции оптимизации блокировки, такие как «спин-блокировка», «устранение блокировки», «огрубление блокировки», но обнаружил, что место может быть относительно большим.Для группы студентов это будет сложнее. чтобы понять, поэтому я решил разделить введение на несколько глав. Я надеюсь, что вы сможете прочитать те части, которые вы не понимаете, несколько раз и медленно изучить их. Я верю, что вы что-то приобретете.


Сообщение в блоге публичного аккаунта синхронизировано с репозиторием Github. Заинтересованные друзья могут помочь дать звезду. Кодировать слова непросто. Спасибо за вашу поддержку.

GitHub.com/pe Маленький PPA...

Рекомендуемое чтение

"Как оптимизировать большое количество if/else, switch/case в коде?
"Как повысить эффективность использования отражения Java?
"Правильное использование позы для журналов Java
"Народный язык понимает, что такое синхронный/асинхронный/блокирующий/неблокирующий

Если у тебя что-то получится, поставь лайк

Обратите внимание на «Программу обезьяны посреди ночи» и поделитесь лучшими галантерейными товарами