пример кода, чтобы показать, как работает Java synchronized block

Я изучаю многопоточность java, я обнаружил, что трудно понять, как работает синхронизированный блок:

 synchronized(Object o){
     // do something
    }

пожалуйста, приведите пример кода, который может показать мне, что объект o заблокирован. Как я понимаю, доступ к объекту o из другого потока будет заблокирован во время исключения синхронизированного блока?

5 ответов


Синхронизация в Java является важной концепцией, так как Java является многопоточным языком, где несколько потоков выполняются параллельно для завершения выполнения программы. В многопоточной среде синхронизация объекта java или синхронизация класса java становится чрезвычайно важной. Синхронизация в Java возможна с помощью ключевых слов java "synchronized"и " volatile". Параллельный доступ к общим объектам в Java вводит в вид ошибок: интерференция потоков и память ошибки согласованности и чтобы избежать этих ошибок, вам необходимо правильно синхронизировать объект java, чтобы разрешить взаимный эксклюзивный доступ критического раздела К двум потокам.

Подробнее: http://javarevisited.blogspot.com/2011/04/synchronization-in-java-synchronized.html#ixzz2LOWwnCjH

пожалуйста, посмотрите на это пример


synchronized ключевое слово может быть применено к статическим / нестатическим методам или блоку кода. Только один поток за раз может получить доступ к синхронизированным методам, и если есть несколько потоков, пытающихся получить доступ к тому же методу, то другие потоки должны ждать выполнения метода одним потоком. Synchronized ключевое слово обеспечивает блокировку объекта и, таким образом, предотвращает состояние гонки

простой пример:

public void synchronized method(){}  
public void synchronized staticmethod(){}
public void myMethod(){

            synchronized (this){             // synchronized keyword on block of  code
            }

}

больше объяснения о синхронизированном блоке и метод:
Синхронизированный блок может выбрать, какой объект он синхронизирует. Синхронизированный метод может использовать только "this" (или соответствующий экземпляр класса для метода синхронизированного класса). Например, они семантически эквивалентны:

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}

последний более гибкий, поскольку он может конкурировать за связанную блокировку любого объекта, часто переменной-члена. Это также более детализировано, потому что вы можете иметь параллельный код, выполняющийся до и после блока, но все же в рамках метода. Конечно, вы можете так же легко использовать синхронизированный метод путем рефакторинга параллельного кода в отдельные несинхронизированные методы. Используйте то, что делает код более понятным.


синхронизация описывает, что если объект или блок объявлен синхронизированным, то только один процесс может получить доступ к этому объекту или блоку одновременно.Ни один другой процесс не может взять объект или блок, пока он не будет доступен .Внутренне каждый объект имеет один флаг с именем "lock" имеет два состояния set и reset. когда процесс запрашивает один объект, проверяется, установлено ли значение блокировки или сброшено. В зависимости от этого один объект доступен процессу в синхронизации . Для лучшего понимания с примером вы можете увидеть эту ссылку. Введите описание ссылки здесь


встроенные блокировки и синхронизация

синхронизация построена вокруг внутренней сущности, известной как внутренняя блокировка или блокировка монитора. (Спецификация API часто ссылается на эту сущность просто как на "монитор".") Встроенные блокировки играют роль в обоих аспектах синхронизации: обеспечение исключительного доступа к состоянию объекта и установление отношений, необходимых для видимости.

каждый объект имеет встроенную блокировку связанный с ней. По соглашению поток, который нуждается в эксклюзивном и согласованном доступе к полям объекта, должен получить внутреннюю блокировку объекта перед доступом к ним, а затем отпустить внутреннюю блокировку, когда это будет сделано с ними. Говорят, что нить владеет внутренним замком между тем, как она приобрела замок и отпустила замок. Пока поток владеет внутренней блокировкой, ни один другой поток не может получить ту же блокировку. Другой поток будет блокировать, когда он попытается получить замок.

когда поток освобождает внутреннюю блокировку, связь происходит до того, как устанавливается между этим действием и любым последующим приобретением той же блокировки.

Замки В Synchronized Методы

когда поток вызывает синхронизированный метод, он автоматически получает внутреннюю блокировку для объекта этого метода и освобождает его, когда метод возвращается. Освобождение блокировки происходит, даже если возврат был вызван неучтенным исключение.

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


поскольку большинство ответов охватывали то, что синхронизировано, я хочу добавить один дополнительный пункт, который не упоминается. Синхронизация метода или включение блока с synchronized гарантирует, что операция/набор операций выполняются как одна атомарная операция, если быть точным, когда один поток выполняет блок синхронизации на объекте, никакой другой поток не может войти в блок, пока поток не завершит свое выполнение и не освободит блокировку, которую он держит, которую он получает при входе в объект. блок.

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

в отличие от указанного @lucifier ,синхронизация и volatile не служат одной и той же цели ,volatile предназначен для обеспечения того, чтобы два потока взаимодействовали друг с другом и получали наибольшее значение обновления из основной памяти вместо доступа к значению из отдельного кэша.это также гарантирует, что поведение "происходит до" для выполнения.

например, определение переменной как volatile (volatile int i=10;) выполнение операции приращения (i++;) в несинхронизированном методе не дает такого же поведения, когда (i++) заключен в синхронизированный блок.