Вопрос о синхронизации Java
В документации по Java говорится, что "невозможно одновременное чередование двух экземпляров синхронизированных методов на одном объекте". Мне нужно знать, синхронизируется ли синхронизированный метод в двух разных экземплярах одного класса от чередования.
например. класс Worker имеет метод под названием process(). У нас есть несколько экземпляров Worker, работающих в их собственных потоках. Мы хотим предотвратить одновременное использование нескольких методов экземпляра(). Будет ли синхронизировано это делать?
Спасибо.
Ответы
Ответ 1
Нет; synchronized
только предотвращает одновременное выполнение несколькими потоками одного метода в том же экземпляре. Если у вас есть n экземпляров, могут быть n потоков, каждый из которых выполняет метод в одном из экземпляров.
Если вам нужно убедиться, что только один поток может выполнить метод во всех экземплярах, вы должны сделать метод static
или сделать метод не synchronized
и скорее использовать блок synchronized
внутри метода, чтобы блокировка в поле private static
.
Изменить: Обратите внимание, что синхронизация в переменной экземпляра private
предпочтительнее иметь метод synchronized
или синхронизировать с this
, а блокировка в переменной экземпляра private static
предпочтительнее иметь static synchronized
метод или метод экземпляра, который синхронизируется на this.getClass()
. Причина в том, что this
и this.getClass()
- это ссылки на объекты, доступные во всей программе, поэтому любой может синхронизировать эти объекты и тем самым блокировать потоки, которые хотят вызвать ваш метод.
Изменить: Также см. комментарий @Cowan ниже - сводка: если вы действительно хотите заблокировать класс, вы можете использовать synchronized (Worker.class)
, а не synchronized (this.getClass())
, в зависимости от того, какой эффект вы хотите в случае подкласса.
Ответ 2
Нет, синхронизация не будет делать этого. Более конкретно, синхронизация на уровне экземпляра не будет делать этого. Вместо этого вам придется синхронизировать на уровне класса.
Например, вместо того, чтобы:
public synchronized method()
{
//do stuff
}
Вам нужно будет ввести код:
public void method()
{
synchronized(this.getClass())
{
//do stuff
}
}
Ответ 3
Нет, если метод static
. A synchronized
нестатический метод принимает блокировку объекта (экземпляра), на который он вызывается, а не класса.
Синхронизированный статический метод принимает блокировку для класса, поэтому это может помочь - но это часто не очень практично.
Что вы можете сделать, это создать статический объект-член в своем классе и выполнить синхронизированный блок на этом (класс-глобальном) объекте в вашем методе process
.
Ответ 4
Нет, синхронизированный метод блокирует конкретный объект ('this'), поэтому 2 экземпляра одного и того же класса будут блокироваться для разных объектов.
Если вы хотите синхронизировать все экземпляры класса, вам нужно использовать синхронизированный блок IN, блокируя статический конечный объект.
Ответ 5
Если вы сделаете метод process
static, он позволит только один вызов метода в одно и то же время.
Если это невозможно, используйте статическую переменную, например Integer lock
;
И используйте synchronized (lock)
внутри вашего метода process
.
то есть
process()
{
synchronized (lock)
{
// all your code
}
}
Ответ 6
Я немного не согласен с 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
}
}
Ответ 7
Только один поток может удерживать блокировку объекта в любой момент времени.
Синхронизированный метод пытается заблокировать экземпляр экземпляра. Другой поток также может содержать блокировку на другом экземпляре того же класса. Другой поток не может ввести другой синхронизированный метод одного и того же экземпляра. то есть это не метод, который заблокирован.
Однако поток может вводить несинхронизированный метод, в то время как другой поток содержит блокировку этого объекта. Защищены только синхронизированные методы.
Статический синхронизированный метод получает блокировку класса, а не объекта. Тем не менее, те же правила, что и нестатический, за исключением другого объекта.
Примечание. Для статического метода нет "экземпляра", даже если вы можете написать код, который, как представляется, использует экземпляр. например instance.staticMethod()