Если я синхронизировал два метода в одном и том же классе, могут ли они одновременно работать на одном и том же объекте ? например:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
Я знаю, что не могу methodA()
дважды запустить один и тот же объект в двух разных потоках. то же самое в methodB()
.
Но могу ли я работать methodB()
в другом потоке, пока methodA()
он еще работает? (тот же объект)
obj.methodB()
является синонимом,A.methodB()
когдаmethodB()
естьstatic
. Поэтому да, они будут блокировать (на мониторе класса, а не объекта)..class
объекта. Так что если у вас естьclass A {static synchronized void m() {} }
. И тогда один поток вызываетnew A().m()
его, получает блокировкуnew A()
объекта. Если затем другой поток вызываетA.m()
его, ВХОДИТ В МЕТОД НЕ ПРОБЛЕМУ, потому что он ищет блокировку наA.class
объекте, в то время как НИКАКИЕ НИТИ не имеют такого рода блокировки . Таким образом, несмотря на то, что вы объявили метод, кsynchronized
нему фактически обращаются два разных потока в одно и то же время . Таким образом: никогда не используйте объектные ссылки для вызова статических методовВ примере methodA и methodB являются методами экземпляра (в отличие от статических методов). Установка
synchronized
метода экземпляра означает, что поток должен получить блокировку («внутреннюю блокировку») для экземпляра объекта, к которому вызывается метод, прежде чем поток сможет начать выполнение любого кода в этом методе.Если у вас есть два разных метода экземпляра, помеченных как синхронизированные, и разные потоки вызывают эти методы одновременно для одного и того же объекта, эти потоки будут бороться за одну и ту же блокировку. Как только один поток получает блокировку, все другие потоки закрываются от всех синхронизированных методов экземпляра этого объекта.
Чтобы два метода работали одновременно, они должны использовать разные блокировки, например:
где синтаксис синхронизированного блока позволяет указать конкретный объект, в котором исполняющий поток должен получить внутреннюю блокировку для входа в блок.
Важно понимать, что, несмотря на то, что мы помещаем ключевое слово «synchronized» в отдельные методы, основная концепция - это внутренняя блокировка за кулисами.
Вот как учебник Java описывает отношения:
Целью блокировки является защита общих данных. Вы будете использовать отдельные блокировки, как показано в приведенном выше примере кода, только если каждая блокировка защищает разные элементы данных.
источник
static synchronized
илиsynchronized (A.class)
Поток Java получает блокировку уровня объекта, когда входит в экземпляр синхронизированного метода java, и получает блокировку уровня класса, когда входит в статический синхронизированный метод java.
В вашем случае методы (экземпляр) одного класса. Поэтому, когда поток входит в синхронизированный метод или блок Java, он получает блокировку (объект, для которого вызывается метод). Таким образом, нельзя одновременно вызывать другой метод для того же объекта, пока не будет завершен первый метод и не будет снята блокировка (для объекта).
источник
private final Object lock = new object();
синхронизированный, чтобы позволить только одному потоку выполнять любой из методов? СпасибоВ вашем случае вы синхронизировали два метода на одном экземпляре класса. Таким образом, эти два метода не могут выполняться одновременно в разных потоках одного и того же экземпляра класса А. Но они могут работать в разных экземплярах класса А.
такой же как:
источник
private final Object lock = new Object();
и теперь используюlock
с синхронизированным блоком в двух методах, то будет ли ваше утверждение верным? IMO, поскольку Object является родительским классом всех объектов, поэтому, даже если потоки находятся в разных экземплярах класса, только один может получить доступ к коду внутри синхронизированного блока за раз. Спасибо.Из документации оракула ссылка
Синхронизация методов имеет два эффекта:
Это ответит на ваш вопрос: для того же объекта вы не можете вызвать второй синхронизированный метод, когда выполняется выполнение первого синхронизированного метода.
Взгляните на эту страницу документации, чтобы понять внутренние блокировки и поведение блокировки.
источник
Думайте о своем коде как о следующем:
Таким образом, синхронизированный на уровне метода просто означает синхронизированный (это). если какой-либо поток запускает метод этого класса, он получит блокировку перед началом выполнения и удержит ее до завершения выполнения метода.
Действительно, это невозможно!
Следовательно, несколько потоков не смогут одновременно запускать любое количество синхронизированных методов для одного и того же объекта.
источник
Просто для ясности, возможно, что как статический синхронизированный, так и нестатический синхронизированный метод могут выполняться одновременно или одновременно, потому что один имеет блокировку уровня объекта и другую блокировку уровня класса.
источник
Ключевая идея с синхронизацией , который не тонет в легко то , что это будет иметь эффект , только если методы вызываются на одном объекте , например - это уже выделены ответы и комментарии -
Ниже приведен пример программы, чтобы четко определить то же самое -
Обратите внимание на разницу в выводе о том, как одновременный доступ разрешен, как и ожидалось, если методы вызываются для разных экземпляров объекта.
Ouput с noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects () прокомментированных -The выход в порядке Methoda в> Methoda Out .. methodB в> methodB Out
и Ouput с прокомментированным synchronizedEffectiveAsMethodsCalledOnSameObject () - выходные данные показывают одновременный доступ метода A Thread1 и Thread0 в выделенном разделе -
Увеличение количества потоков сделает это еще более заметным.
источник
Нет, это невозможно, если бы это было возможно, то оба метода могли бы одновременно обновлять одну и ту же переменную, что могло бы легко повредить данные.
источник
Да, они могут запускать оба потока одновременно. Если вы создаете 2 объекта класса, так как каждый объект содержит только одну блокировку, и каждый синхронизированный метод требует блокировки. Поэтому, если вы хотите запустить одновременно, создайте два объекта, а затем попробуйте запустить, используя ссылку на этот объект.
источник
Вы синхронизируете его с объектом, а не с классом. Таким образом, они не могут работать одновременно на одном и том же объекте
источник
Два разных потока выполняют общий синхронизированный метод для одного объекта, так как объект один и тот же, когда один поток использует его с синхронизированным методом, ему придется изменить блокировку, если блокировка включена, этот поток перейдет в состояние ожидания, если блокировка отключена, то он может получить доступ к объекту, в то время как он получит доступ, включит блокировку и снимет блокировку только после завершения ее выполнения. когда прибудет другой поток, он изменит блокировку, так как он включен, он будет ждать, пока первый поток завершит свое выполнение, и снимет блокировку, установленную для объекта, после снятия блокировки второй поток получит доступ к объекту и он включит блокировку до ее выполнения. поэтому выполнение не будет не параллельным, оба потока будут выполняться один за другим,
источник