Вопрос о Java синхронизирован - PullRequest
12 голосов
/ 02 июня 2011

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

Например, класс Worker имеет метод с именем process ().У нас есть несколько экземпляров Worker, работающих в своих собственных потоках.Мы хотим предотвратить одновременное выполнение метода process () более чем одним экземпляром.Будет ли синхронизирован делать это?

Спасибо.

Ответы [ 7 ]

26 голосов
/ 02 июня 2011

Нет;synchronized не позволяет нескольким потокам одновременно выполнять метод в том же экземпляре.Если у вас есть n экземпляров, может быть n потоков, каждый из которых выполняет метод в одном из экземпляров.

Если вам нужно убедиться, что только один поток можетвыполнить метод во всех случаях, вы должны сделать метод static или сделать метод не-synchronized и вместо этого использовать блок synchronized внутри метода для блокировки поля private static.

Edit: Обратите внимание, что синхронизация с переменной экземпляра private предпочтительнее, чем метод synchronized или синхронизация с this, и что блокировка переменной экземпляра private static предпочтительнее, чем метод static synchronized илиметод экземпляра, который синхронизируется на this.getClass().Причина в том, что this и this.getClass() являются ссылками на объекты, которые доступны по всей программе, поэтому любой может синхронизироваться с этими объектами и тем самым блокировать потоки, которые хотят вызвать ваш метод.

Редактировать: Также,см. комментарий Коуэна ниже - сводка: если вы действительно хотите заблокировать класс, вы можете использовать synchronized (Worker.class) вместо synchronized (this.getClass()), в зависимости от того, какой эффект вы хотите получить в случае подкласса.

3 голосов
/ 02 июня 2011

Нет, синхронизированный не будет этого делать.Более конкретно, синхронизация на уровне экземпляра не сделает этого.Вместо этого вам придется синхронизироваться на уровне класса.

Например, вместо:

public synchronized method()
{
    //do stuff
}

Вам придется кодировать как:

public void method()
{
    synchronized(this.getClass())
    {
        //do stuff
    }
}
2 голосов
/ 02 июня 2011

Нет, метод синхронизировал блокировки на конкретном объекте ('this'), поэтому 2 экземпляра одного класса будут блокироваться на разных объектах.

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

2 голосов
/ 02 июня 2011

Нет, если метод не является static.synchronized Нестатический метод принимает блокировку для объекта (экземпляра), к которому он вызывается, а не для класса.

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

Что вы можете сделать, это иметь статический объект-член в вашем классе и создать синхронизированный блок для этого (глобального) класса в вашем методе process.

0 голосов
/ 02 июня 2011

Только один поток может одновременно удерживать блокировку объекта.

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

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

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

Примечание. Для статического метода не существует «экземпляра», даже если вы можете написать код, который будет использовать экземпляр.например, instance.staticMethod()

0 голосов
/ 02 июня 2011

Я немного не согласен с Aasmund - хотя и согласен немного одновременно: если вы используете такую ​​конструкцию:

class Worker {
...
 public synchronized void process() {...}
}

, то Aasmund прав - это не предотвратит множественные случаикласс Worker для параллельного выполнения process().Однако вы можете использовать ключевое слово synchronized для синхронизации статического члена, чтобы этого не происходило:

class Worker {
 static Object o = new Object();
 ...
 public void process() {
  synchronized(o) {
   ...//perform the work here
  }
 }
0 голосов
/ 02 июня 2011

Если вы сделаете метод process статическим, он разрешит только один вызов метода одновременно.

Если это невозможно, укажите статическую переменную, скажем, Integer lock; И используйте synchronized (lock) внутри вашего метода process. то есть

process()
{
    synchronized (lock)
    {

        // all your code

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