Как работает синхронизация в Java?

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

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


person Raj    schedule 25.06.2012    source источник
comment
Каков источник этого утверждения и что вас смущает? Кажется, ты это понимаешь. Будьте осторожны с взаимоблокировкой при доступе к одному синхронизированному методу из другого.   -  person Sridhar    schedule 25.06.2012
comment
Re: ...другие два будут заблокированы. Текущему выполняемому потоку, который уже имеет блокировку, не будет запрещено вызывать другой синхронизированный метод для того же объекта, однако любой другой поток будет заблокирован (т.е. вынужден ждать, пока ему не будет предоставлена ​​блокировка). У Макса есть хороший ответ, в котором говорится о том, блокируете ли вы сам объект (т.е. это) или полностью другую объектную переменную.   -  person Brad    schedule 25.06.2012
comment
можно понять основы синхронизации отсюда dzone.com/articles /как-синхронизация-работает-в-java-часть-1   -  person Abdul Mohsin    schedule 13.03.2018


Ответы (8)


Синхронизация в java выполняется путем запроса монитора на какой-то конкретный объект. Поэтому, если вы сделаете это:

class TestClass {
    SomeClass someVariable;

    public void myMethod () {
        synchronized (someVariable) {
            ...
        }
    }

    public void myOtherMethod() {
        synchronized (someVariable) {
            ...
        }
    }
}

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

Когда вы ставите synchronized в метод, это в основном означает то же, что и synchronized (this), то есть синхронизацию объекта, на котором выполняется этот метод.

Это:

public synchronized void myMethod() {
    ...
}

Означает то же, что:

public void myMethod() {
    synchronized (this) {
       ...
    }
}

Поэтому, чтобы ответить на ваш вопрос - да, потоки не смогут одновременно вызывать эти методы в разных потоках, поскольку они оба содержат ссылку на один и тот же монитор, монитор объекта this.

person bezmax    schedule 25.06.2012
comment
Макс, термин "замок" в вашем последнем предложении вводит в заблуждение. Я думаю, вы хотели сказать ... поскольку они оба ссылаются на один и тот же монитор. Два потока не могут одновременно удерживать блокировку одного и того же монитора. - person Brad; 25.06.2012
comment
Не поняв того, что вы передали в первом абзаце, не могли бы вы объяснить это более простыми словами. - person userab; 03.04.2017
comment
насколько я понял, блокируются только синхронизированные методы. Несинхронизированные методы объекта могут быть вызваны в любое время любым потоком, как указано в вопросе, подразумевает, что другие потоки могут вызывать параллельно * или в то же время методы, которые не синхронизированы - person moldovean; 21.01.2018
comment
@moldovean Как я объяснил в своем ответе, синхронизированный метод - это не что иное, как ярлык для синхронизации блока с объектом. - person bezmax; 23.01.2018

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

person Ajinkya    schedule 25.06.2012

Каждый объект Java (экземпляр класса) имеет объект мьютекса. Синхронизированное ключевое слово перед методом означает, что работающий поток должен получить блокировку мьютекса для этого объекта. По факту,

public synchronized doSomething(){
   ...
}

Точно так же, как это:

public  doSomething(){
   synchronized(this){
      ...
   }
}

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

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

person Miquel    schedule 25.06.2012

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

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

person Ahmad    schedule 25.06.2012

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

Помните, что синхронизированный метод аналогичен обычному методу, окруженному

synchronized(this) {
    // method body
} 
person Johannes Weiss    schedule 25.06.2012

Это правда, и это происходит таким образом. Также необходимо согласовать данные этого объекта.

Предположим, что этой проверки нет, и есть переменная x, которой манипулируют 2 разных синхронизированных метода xxx() и yyy().

поэтому, если поток A получает блокировку метода xxx(), который манипулирует x=5, а второй поток B получает блокировку метода yyy() и манипулирует x=-5, то в конце метода xxx() поток A ожидает x=5 но он получит x=0, что неверно.

Вот почему он реализован таким образом.

person Pramod Kumar    schedule 25.06.2012

Если класс имеет 4 метода синхронизации, то одновременно только один поток будет иметь доступ к этим методам. Я предполагаю, что сомнения здесь были в том, что каждый поток может одновременно обращаться к синхронизированным методам diff для одного экземпляра класса. Ответ - нет. Только один поток может одновременно обращаться к синхронизированным методам.

person Farhaz Malik    schedule 08.02.2017

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

person user207421    schedule 25.06.2012