Reputation: 35572
Assume the following class
public class TestObject{
public void synchronized method1(){
//some 1000 lines of code
}
public void method2(){
//some 1000 lines of code
}
}
Let's assume there are two threads accessing the same instance of TestObject class, let's call them t1 and t2. I want to know what will happen in the following scenario.
My understanding is that for the first question, the thread t2 will not be given permission as the object will be locked by t1. For the second question, the thread t2 will be granted access and takes lock on the object and will stall t1 from execution. But my assumption was wrong. Can anyone explain this?
Thanks
Upvotes: 6
Views: 513
Reputation: 26586
One method is synchronized while the other is not. So no matter whether the lock on an Object (in this is case the instance the method belongs to) has been acquired or not, the non-synchronized method will execute unimpeded (since it foes not try to acquire or wait for a lock). Which means in both cases both threads will run without waiting for each other - resulting in a possibly inconsistent state of the object.
Upvotes: 2
Reputation: 54516
When you declare a method to be synchronized, e.g.:
public synchronized void foo() {
// Do something
}
the compiler treats it as though you had written this:
public void foo() {
synchronized (this) {
// Do something
}
}
In your example you have one synchronized method and one non-synchronized. This means that only access to method1
will be locked. Locking checks are only done on entry to a synchronized
block, so calling method2
will not trigger any locking.
To answer your two questions, then, in both cases the two threads will be allowed to proceed because they are not trying to obtain a lock on the same object. If you declare method2
to be synchronized (or manually add a synchronized (this)
block) then one thread will be forced to wait for the other.
Remember: synchronizing on an object does not prevent other threads calling methods on that object. It only prevents another thread entering a synchronized block with the same lock object.
Incidentally, it's often better to have an internal lock object rather than declaring methods to be synchronized, e.g.
class Foo {
private final Object LOCK = new Object();
public void doSomething() {
synchronized (LOCK) {
// Whatever
}
}
}
Otherwise I can break your thread-safety by doing this:
class MessEverythingUp {
public MessEverythingUp(Foo foo) {
synchronized (foo) {
while (true) {
System.out.println("Pwnd ur thread safety");
}
}
}
}
Since I'm locking the instance of foo, your synchronized methods (with their implicit "synchronized (this)") will not be able to obtain a lock and will block forever. Most importantly, you cannot prevent this because I can synchronize on whatever object I like. Obviously the example is extreme but you can get nasty, subtle deadlock bugs if you're not careful about this sort of thing.
Upvotes: 4
Reputation: 33082
In both cases, the second thread will be given permission to execute its method.
Since only one of these two methods contains the synchronized
keyword, both of these methods can be executed simultaneously. The restriction is that only one method with that keyword can be executed at any given time, because executing that method requires a lock on the object. A thread without the keyword requires no lock and will always be allowed to execute regardless of the object being locked.
I also assume here that the 1000 lines of code in method2
does not contain a block like this:
synchronized (this) { }
If it does, then the results will be different.
synchronized
line, it will wait for t1 to finish method1
and release its lock before continuing.synchronized
code block. If it is, t2 will wait until t1 exits the block and releases the lock before beginning. If t1 has not yet entered the synchronized
block, then t2 will acquire the lock, and t1 will wait as soon as it gets to the synchronized code block until t2 completes the method and releases the lock.Upvotes: 3
Reputation: 15656
Both threads will execute as if the lock does not exist.
The thread accessing method2 will never know that it should get a lock so it will execute even if an other thread holds the lock. Only synchronized methods will reserve the lock since synchronization is optional and not always wanted or even necessary.
If both threads execute method1 one of them will block until the other thread exits the method and releases the lock.
To make sure only one thread executes and all others wait you have to make both methods synchronized.
Upvotes: 0
Reputation: 54094
Only the method with the keyword synchronized holds a lock for this object when a thread is running in that method.
Had both method 1 and method 2 been declared as synchronized, one thread would block the other even though they are trying to run different methods.
In your example only 1 method is blocking by an implicit lock.
As a result t1 and t2 can be running concurrently in method 1 and method 2 (or vice versa).
Only when trying to access method 1, a t1 or t2 would block if the lock has already been acquired
Upvotes: 8
Reputation: 2224
method1() is synchronized and hence called as thread safe method. When multiple threads try to access this method simultaneously then only the lock on instance object will work.
method2() is not synchronized and hence is a thread unsafe method, other threads can call this method even if the some other thread has lock on the instance, that is why this method is called as thread unsafe method.
In both cases you mentioned one thread will get lock on the instance by calling method1() and other thread will try to access method2() which is unsafe and hence both thread will execute.
with regards
Tushar Joshi, Nagpur
Upvotes: 0