Как делает синхронизируемую работу в Java

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

15
задан Marian Paździoch 8 August 2016 в 14:08
поделиться

4 ответа

In Java, each Object provides the ability for a Thread to synchronize, or lock, on it. When a method is synchronized, the method uses its object instance as the lock. In your example, the methods bow and bowBack are both synchronized, and both are in the same class Friend. This means that any Thread executing these methods will synchronize on a Friend instance as its lock.

A sequence of events which will cause a deadlock is:

  1. The first Thread started calls alphonse.bow(gaston), which is synchronized on the alphonse Friend object. This means the Thread must acquire the lock from this object.
  2. The second Thread started calls gaston.bow(alphonse), which is synchronized on the gaston Friend object. This means the Thread must acquire the lock from this object.
  3. The first thread started now calls bowback and waits for the lock on gaston to be released.
  4. The second thread started now calls bowback and waits for the lock on alphonse to be released.

To show the sequence of events in much more detail:

  1. main() begins to execute in the main Therad (call it Thread #1), creating two Friend instances. So far, so good.
  2. The main Thread starts its first new Thread (call it Thread #2) with the code new Thread(new Runnable() { .... Thread #2 calls alphonse.bow(gaston), which is synchronized on the alphonse Friend object. Thread #2 thus acquires the "lock" for the alphonse object and enters the bow method.
  3. A time slice occurs here and the original Thread gets a chance to do more processing.
  4. The main Thread starts a second new Thread (call it Thread #3), just like the first one. Thread #3 calls gaston.bow(alphonse), which is synchronized on the gaston Friend object. Since no-one has yet acquired the "lock" for the gaston object instance, Thread #3 successfully acquires this lock and enters the bow method.
  5. A time slice occurs here and Thread #2 gets a chance to do more processing.
  6. Thread #2 now calls bower.bowBack(this); with bower being a reference to the instance for gaston. This is the logical equivalent of a call of gaston.bowBack(alphonse). Thus, this method is synchronized on the gaston instance. The lock for this object has already been acquired and is held by another Thread (Thread #3). Thus, Thread #2 has to wait for the lock on gaston to be released. The Thread is put into a waiting state, allowing Thread #3 to execute further.
  7. Thread #3 now calls bowback, which in this instance is logically the same as the call alphonse.bowBack(gaston). To do this, it needs to acquire the lock for the alphonse instance, but this lock is held by Thread #2. This Thread is now put into a waiting state.

And you are now in a position where neither Thread can execute. Both Thread #2 and Thread #3 are waiting for a lock to be released. But neither lock can be released without a Thread making progress. But neither thread can make progress without a lock being released.

Thus: Deadlock!

Deadlocks very often depend on a specific sequence of events occurring, which can make then difficult to debug since they can be difficult to reproduce.

26
ответ дан 1 December 2019 в 01:53
поделиться

Синхронизированный имеет два эффекта :

  • Во-первых, два вызова синхронизированных методов для одного и того же объекта не могут чередоваться. Когда один поток выполняет синхронизированный метод для объекта, все другие потоки, которые вызывают синхронизированные методы для того же блока объекта (приостанавливают выполнение), пока первый поток не завершится с объектом.
  • Во-вторых, когда синхронизированный метод завершается, он автоматически устанавливает отношение «происходит до» с любым последующим вызовом синхронизированного метода для того же объекта. Это гарантирует, что изменения состояния объекта видны всем потокам.

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

2
ответ дан 1 December 2019 в 01:53
поделиться

All synchronized functions for the same object. Marking a method "synchronized" is very similar to putting a "synchronized (this) {" block around the entire contents of the method. The reason I don't say "identical" is because I don't know offhand whether the compiler emits the same bytecode or not, but AFAIK the defined runtime effect is the same.

The deadlock is a classic locking inversion. One thread locks alphonse. Then (or simultaneously on a multi-core system) the other thread locks gaston. This part requires that the scheduling of the threads just so happens to interleave at the right points.

Each thread (in whatever order or simultaneously) then attempts to acquire a lock which is already held by the other thread, and hence each thread goes to sleep. Neither will wake until the other releases its lock, but neither will release its lock until it wakes (or is terminated).

2
ответ дан 1 December 2019 в 01:53
поделиться

Синхронизированный метод аналогичен включению кода всех этих методов в блок

synchronized(this) {
  /// code here ...
}

.

Для для данного экземпляра объекта o только один поток может одновременно запускать любой блок synchronized (o) . Любой другой поток, который пытается это сделать, будет зависать до тех пор, пока поток, который выполняет этот блок (не имеет синхронизированную блокировку ), не выйдет из этого блока (освободит блокировку).

В вашем случае тупик возникает, когда Альфонс начинает кланяться в потоке 1, тем самым входя в синхронизированный блок. Поток 1 затем вытесняется системой, так что поток 2 может начаться и получить поклон Гастона. Но Гастон пока не может поклониться, потому что он синхронизируется на Alphonse, и у Thread 1 эта блокировка уже есть. Таким образом, он будет ожидать, когда поток 1 покинет этот блок. Затем система заменит поток 1 обратно, который попытается заставить Альфонса поклониться назад. За исключением того, что он не может сделать это, потому что поток 2 имеет синхронизированную блокировку на Gaston. Обе Нити теперь застряли, ожидая, пока другая закончит поклон, прежде чем сможет поклониться ...

2
ответ дан 1 December 2019 в 01:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: