i have a class named sell_ticket extends thread.
static int num = 0;
Object obj = new Object();
@Override
public void run() {
while(true){
synchronized (obj){
if(num < 10000){
System.out.println("sell ticket " this.getName() " " this.num);
num ;
}
else
break;
}
}
}
and then i new two object in this.then i run every object.like this:
sell_ticket s1 = new sell_ticket();
sell_ticket s2 = new sell_ticket();
s1.setName("s1");
s2.setName("s2");
s1.start();
s2.start();
but i discover that s1 and s2 will run at the same time.s1 will output "sell ticket s1 0".s2 will output "sell ticket s2 0",too.i think the normal solution should output only one of them.for example,if s1 output num is zero,it means s1 start firstly,then s2 should start from num is one,so s2 shoulen't output "sell ticket s2 0".But s2 still output "sell ticket s2 0".why does it happen?
CodePudding user response:
Your thread code is using synchronized
, but the object that each thread synchronizes on is unique for that thread. No other thread is using the same object to synchronize on. So each thread that runs the synchronized (obj) { ... }
block in your code will always obtain the lock for obj
, because nobody else even has access to that lock object.
Here is a really simple example showing the underlying behavior involved. All it does is print out the name of the thread (ex: "Thread-0") along with the default .toString()
output for the lock object. This shows clearly that "Thread-0" is using java.lang.Object@3c71ae76
as its lock object, while "Thread-1" is using java.lang.Object@218e04a1
– that is, a totally different object.
class NotReallySynchronizedThread extends Thread {
private final Object object = new Object();
@Override
public void run() {
synchronized (object) {
System.out.println(this.getName() " just obtained lock on object " object);
}
}
}
I ran above with this:
new NotReallySynchronizedThread().start();
new NotReallySynchronizedThread().start();
And it produced this output - the lock objects are clearly different: java.lang.Object@3c71ae76
vs. java.lang.Object@218e04a1
:
Thread-0 just obtained lock on object java.lang.Object@3c71ae76
Thread-1 just obtained lock on object java.lang.Object@218e04a1
To fix your program, you need each thread – all threads – to use the same, single object to synchronize on.
Here's an updated example where the thread constructor now requires an object to use as a shared lock:
class SynchronizedThread extends Thread {
private final Object sharedLock;
public SynchronizedThread(Object sharedLock) {
this.sharedLock = sharedLock;
}
@Override
public void run() {
synchronized (sharedLock) {
System.out.println(this.getName() " just obtained lock on object " sharedLock);
}
}
}
And an example showing the usage, along with output. This time, the threads are clearly using the same object to lock on - java.lang.Object@330152f7
.
Object sharedLock = new Object();
new SynchronizedThread(sharedLock).start();
new SynchronizedThread(sharedLock).start();
Thread-0 just obtained lock on object java.lang.Object@330152f7
Thread-1 just obtained lock on object java.lang.Object@330152f7