1

I have to questions:
1. What part of the code of a synchronized method, the synchronization block?
for example:

public class example{

  public synchronized void f1(){
    //some code....
     f2();
    }
    public synchronized void f2()
    {
      //some code...
    }
}
public void main(String[[] args)
{
   Thread t1 = new Thread(new Runnable()
   {public void run(){f1();)},
          t2 = new Thread(new Runnable()
   {public void run(){f2();};
   t1.start();
   t2.start();

}

so after t1 is started, t2 can't start - because its waiting for t1. But whan t1 starts doing f2, does that mean that t2 can enter f1?

And if you may, please explain this deadlock example. i didn't get it. source: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s"
                + "  has bowed to me!%n", 
                this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }}).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }}).start();
    }
}
789
  • 718
  • 1
  • 10
  • 30
  • of the 2 questions, the first is unclear (doesn't compile, it's hard to tell what you want), the question about the bowing example is already answered. – Nathan Hughes Aug 12 '14 at 20:52
  • so when `alphonse.bow(gaston);` is activated, alphonse is locked in his `bow()` function, and cannot do anything else (e.g. `bowBack()` ) until he exit the `bow()` function ? – 789 Aug 12 '14 at 20:57
  • No, it is that when `alphonse` tries to call `gaston.bowBack()` it is unable to complete because `gaston` is already locked due to the second thread calling `gaston.bow()`. So gaston is waiting for `alphonse.bow()` to complete (in order to call `alphonse.bowBack()`), and alphonse is waiting for `gaston.bow()` to complete in order to call `gaston.bowBack()`. As a result, neither one will ever complete. – Trevor Freeman Aug 12 '14 at 21:02

2 Answers2

1

A synchronized method in Java locks on the entire method, and importantly, it locks on the instance of the object the method is being called on. This means that two synchronized methods in the same object share the same lock, and so cannot be concurrently executed by different threads.

E.g. In the below class

public class myClass
{
  synchronized void method1()
  {

  }

  synchronized void method2()
  {

  }
}

method1() and method2() can never be called concurrently on the same object since the code is reasonably equivalent to:

public class myClass
{
  void method1()
  {
    synchronized(this)
    {
      // ...
    }
  }

  void method2()
  {
    synchronized(this)
    {
      // ...
    }
  }
}

If you want both methods to be independently synchronized on different locks, then you can do something like the following:

public class myClass
{
  private final Object method1Lock = new Object();
  private final Object method2Lock = new Object();

  void method1()
  {
    synchronized(method1Lock)
    {
      // ...
    }
  }

  void method2()
  {
    synchronized(method2Lock)
    {
      // ...
    }
  }
}
Trevor Freeman
  • 7,112
  • 2
  • 21
  • 40
0

Deadlock example: Since two threads (executing instance of an process, or even light weight processes as some operating systems call them) acquire the same lock one of them will always get the lock and the other has to wait until the one that acquired the lock first (this is determined by the JVM, think about the JVM as the operating system - someone has to guarantee atomicity of the lock, that is up to the JVM) finished. In the example one thread will execute bow() followed by a bowBack(), but by the time bowBack() is executed the other thread has performed a acquire on the same lock (by calling bow()), leaving the other thread in a waiting state, which depends on the first thread and the first thread depends on the same lock when calling bowBack() - a circular dependency has occurred, i.e. a deadlock.

from the oracle doc:

First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

The example further states that its extremely likely that a deadlock will occur, implying that it does not have to occur. This is because the first thread that got the lock could finish executing its bowBack() before the second thread acquires the lock, i.e. calls bow() (I use acquire the lock as terminology from operating system theory which came up with the original language for this once), it is up to the JVM to decide which thread can execute at what time (the actual scheduling of the threads executing scheme so to say, and changing executing thread (called a context switch) is a bit costly thus the JVM might decide to let the first thread execute for a longer period with the result of a deadlock not occurring). Thinking of thread scheduling one is best of by consider it as a pretty random thing, if a deadlock can occur it sooner or later will, one run of the program (or another kind of cycle e.g. a method that spawns two threads like in the example) might give a deadlock another might not. Multithreading is a lot about considering what to lock down on, and not combining locks in a fashion that can spawn a deadlock.

Maybe you should try to get the example not to deadlock by for example sleeping one thread for a while (e.g. try with 1 ms before entering bow, before say gaston.bow()) and see what happens, remember there are no guarantees by doing so, sleeping one thread does not actually make the code thread safe, the deadlock will only occur less frequently.

What about then introducing a couple of more threads doing bow() - Did the sleep actually help, or just postpone the problem....?

ASF
  • 64
  • 11
  • ` first thread and the first thread depends on the same lock when calling bowBack()` are you saying that bow() and bowBack() are using the same lock?? that doesn't make any sense. why would two different functions will use the same lock? – 789 Aug 12 '14 at 20:47