Поговорим о синхронизированной реализации (реентерабельность блокировки, расширение блокировки)

JVM

основное использование

  1. Synchronized помещается в метод экземпляра, а объект блокировки является текущим объектом this.
  2. Synchronized помещается в метод класса (статический метод), а объект блокировки — это объект класса в области метода.
  3. Синхронизированный измененный блок кода, то есть синхронизированный (объект) {}, объект блокировки - это объект в ()

synchronizedПри использовании для изменения метода он передаетсяACC_SYNCHRONIZEDИдентификатор для синхронизации потоков.

synchronizedПри использовании для украшения блоков кода это делается с помощьюmonitorenterиmonitorexitинструкция по завершению

Принцип реализации

  • уровень кода, Синхронизированное ключевое слово.

  • Уровень байт-кода JAVA, метод синхронизацииACC_SYNCHRONIZEDОпределение декоративного метода, использование синхронизированного блока кодаmonitorenterиmonitorexitРеализованы две инструкции.

  • Уровень JVM, Без блокировки, Блокировка смещения, Легкая блокировка, Тяжелая блокировка.

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

  • аппаратный уровень, — это семафор, блокирующий северный мост.

1) КПМХЧГ

  • Используется для сравнения и замены операндов, примитивная поддержка ЦП для CAS
  • Неатомарный, впервые использованный в одноядерных процессорах.

2) префикс БЛОКИРОВКА

  • Процессор гарантирует атомарность модифицированных им инструкций.

  • Отключить изменение порядка

  • Кэш сброшен в память

Чем добиться?

image.png

1. Отметить слово в заголовке объекта

image.png

image.png

Блокировка смещения

if (锁的标记位 == 01) {
    if (偏向标记是1){
        是偏向锁且可偏向
        boolean CAS操作结果 = CAS操作替换偏向线程的ID为当前线程
        if ( CAS操作结果 == 成功){
            当前线程获得锁
            执行同步代码块
        } else {
            CAS操作失败
            开始【偏向锁的撤销】{
                等到全局安全点
                var 状态 = 检查原来持有锁的线程的状态
                if (状态 == terminated || 已经退出同步代码区)
                    原线程释放锁
                    当前线程获得锁
                else if (状态 == runnable && 未退出同步代码区){
                    执行【偏向锁膨胀到轻量级锁】的过程{
                        原持有锁的线程栈幁分配锁记录、替换MarkWord并指向对象地址、执行同步代码块、CAS操作释放锁
                        当前线程执行轻量级锁的抢锁过程{
                            CAS自旋
                            if (自旋一定次数还没有获取锁){
                                膨胀到重量级锁
                            }
                        }
                    }
                }
            }
        }
    }else {
        goto line 4 执行CAS操作
    }
}else {
    不是偏向锁
}

Легкий замок

if (锁的标记位 == 00) {
    是轻量级锁
    执行轻量级锁的抢占{
        当前线程的栈幁中 分配 【锁记录】,【锁记录】由两个部分构成,【displaced Markword】 和 【onwer指针】
        把锁对象的【对象头】中的【Markword】拷贝到锁记录中的【displaced Markword】中
        onwer指针 指向 该锁对象
        CAS修改锁对象的对象头,使其中的【指向线程锁记录的指针】 这一字段指向当前线程
        if (CAS操作成功){
            当前线程持有锁
        }else{
            CAS操作失败
            CAS自旋
            if (自旋超过一定次数还没有成功){
                升级为重量级锁{
                    改变Markword
                    挂起当前线程
                }
            }
        }
    }
    }else {
    不是轻量级锁
}

2. Объект монитора монитора

В Java неявно в каждом объекте есть объект, называемый монитором (монитор объекта). Объект монитора существует в заголовке объекта Mark Word объекта Java. Исходный код этого объекта реализован на C++.

 class ObjectMonitor {
...
  ObjectMonitor() {
    _header       = NULL; //markOop object header
    _count        = 0;    
    _waiters      = 0,   //Number of waiting threads
    _recursions   = 0;   //Thread reentry times
    _object       = NULL;  //Store Monitor object
    _owner        = NULL;  //Thread to get ObjectMonitor object
    _WaitSet      = NULL;  //List of threads in wait state
    _WaitSetLock  = 0 ; 
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ;	// One way list
    FreeNext      = NULL ;
    _EntryList    = NULL ; //Thread waiting for lock BLOCKED
    _SpinFreq     = 0 ;   
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ; 
    _previous_owner_tid = 0; //ID of the previous owning thread of the monitor
  }
...

Процесс

20180908110545722.png

благодарный:Jacksgong

блокировка повторного входа

  • блокировка повторного входа в блокировку

    • Просто оцените предвзятый идентификатор потока в слове метки
  • Блокировка повторного входа для облегченных замков

    • Снова поместите запись блокировки, но отображаемое ключевое слово равно нулю

    • Определяем количество повторных входов по количеству записей блокировки

    • Старший бит — это первая блокирующая запись.

  • Блокировка повторного входа для тяжеловесных блокировок

    • операционная система для реализации