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());
} }
精彩评论