开发者

Synchronization problem

  public class PingPong implements Runnable {
      synchronized void hit(long n) {
          for (int i = 1; i < 3; i++)
              System.out.print(n + "-" + i + " ");
      }
      public static void main(String[] args) {
          new Thread(new PingPong()).start();
          new Thread(new PingPong()).start();
      }
      public void run() {
          hit(Thread.currentThread().getId());
      }
  }

The above code gives me output 8-1 9-1 8-2 9-2

But as the function is synchronized it should give output 8-1 8-2 9-1 9-2 开发者_运维问答or 9-1 9-2 8-1 8-2

Can anyone explain please?


'synchronized' on a method synchronizes all accesses of that method on a particular object.

So if you have 1 PingPong object no 2 threads will simultaneously enter its hit method, but with 2 objects one thread can enter the hit method of one of the objects while another thread runs the hit object of the other.

This makes sense because you usually use synchronized to ensure undisturbed access to stuff local to the current object. If your object represents some external entity to which threads sometimes need undisturbed access, make your object a singleton.


To get the behaviour you want, try making the following change:

 public class PingPong implements Runnable {
      synchronized void hit(long n) {
          for (int i = 1; i < 3; i++)
              System.out.print(n + "-" + i + " ");
      }
      public static void main(String[] args) {
          PingPong p = new PingPong();
          new Thread(p).start();
          new Thread(p).start();
      }
      public void run() {
          hit(Thread.currentThread().getId());
      }
  }

With only a single instance of PingPong, the synchronized modifier on hit() will prevent one thread from interrupting the other, and your output will be either X-1 X-2 Y-1 Y-2 or visa-versa.


As per http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

First, it is not possible for two invocations of synchronized methods on the same object to interleave.

So since you have two PingPong objects the synchronized keyword does not work as you expected.


Nope .. synchronized simply mean that a specific method will not be executed by two threads at the same time, but if you have two threads working they can call that method in any order anyway. Simply, they will not access at the same time.

Moreover, it synchronizes on the object instances. Being two instances, there is no synchronization at all.


You have no lock or unlock flags. so they will both run at the same time.

T1->run()->hit(); forloop
T2->run()->hit(); forloop


Change your code to

public class PingPong2 implements Runnable {

private static Object obj = new Object();
    void hit(long n) {
     synchronized(obj)
     {
    for (int i = 1; i < 3; i++)
        System.out.print(n + "-" + i + " ");
     }
}
public static void main(String[] args) {
    new Thread(new PingPong2()).start();
    new Thread(new PingPong2()).start();
}
public void run() {
    hit(Thread.currentThread().getId());
  }   }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜