Threading & locks in java - java

I heard that every object in java has an intrinsic lock associated with it. what if a thread take this lock to invoke synchronized method. does that mean no another thread can access any methods in this object or the synchronized methods only ?!

Just one thread can access synchronized methods at the same time.
See official documentation:
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.

synchronized on an instance method is shorthand for synchronized (this) { } around the entire method body. For static methods it is the equivalent of synchronized (this.class) { }. So just think synchronized (obj) { }.
Only a single thread can acquire a lock, so superficially only one thread can enter at a time. Loser threads block until the lock is available.
That's not the entire story. If somewhere within a synchronized block (perhaps in another method) the thread calls this.wait(); (with optional arguments), then that thread releases the lock for the duration of wait(). During this time the lock is available, for instance, to call this.notifyAll().
Also it worth noting that the lock is reentrant. Another, or the same, synchronized method can be called recursively.

Related

Can two threads execute the same synchronized block of code on the same object if they use different monitors?

I'm newish to Java concurrency and I'm trying to better understand monitors.
Suppose I have one object, with a method that takes some kind of reference argument and uses that argument as a monitor in a synchronized block:
class Entity() {
public void myMethod(Object monitor) {
synchronized(monitor) {
// critical stuff
}
}
}
Can two threads enter that section at the same time on the same entity if they use different objects for the monitor?
final Entity myEntity = new Entity();
for (int i = 0; i < 3; i++) {
new Thread() {
public void run() {
// Can these all run concurrently?
myEntity.myMethod(new Object());
}
}.start();
}
If I understand monitors correctly, then yes, all the threads can enter the synchronized block at the same time, because each monitor acts as a totally different mutex and none of the threads are aware of the other threads in that block.
It's been difficult to find documentation on this because tutorials mostly seem to just use "this" as the monitor.
Can two threads enter that section at the same time on the same entity
if they use different objects for the monitor?
From the oracle tutorial one can read:
Every object has an intrinsic lock associated with it. By convention,
a thread that needs exclusive and consistent access to an object's
fields has to acquire the object's intrinsic lock before accessing
them, and then release the intrinsic lock when it's done with them. A
thread is said to own the intrinsic lock between the time it has
acquired the lock and released the lock. As long as a thread owns an
intrinsic lock, no other thread can acquire the same lock. The other
thread will block when it attempts to acquire the lock.
This informally means that one can synchronize using any Java Object. A block enclosed by a clause synchronized on a single object instance will be executed sequentially, i.e., executed by the thread holding the lock of the object being synchronized.
Can two threads enter that section at the same time on the same entity
if they use different objects for the monitor?
Yes, multiple threads can execute (in parallel) the same code region wrapped with a synchronized clause as long as each of those threads is synchronizing using different object instances.
One can also synchronize using the class itself, rather than its instances:
synchronized (SomeClass.class){
System.out.println("Hello World");
}
In such cases, all the threads that use the clause synchronized on the class SomeClass, will have to synchronize among each other.
One can also use clause synchronized on methods (e.g., public synchronized void method2()); for non-static methods the object being synchronized will be the object to which that method belongs, whereas for static methods (e.g., public static synchronized void method1()) will be class itself to which that method belongs.

How multiple synchronized key words work in a single class?

package anonymous;
public class A {
public static int counter=0;
public static void main(String[] args) {
synchronized (args) {
//some logic
}
synchronized (args) {
//some logic
}
}
}
Let say one thread is executing in one synchronized block. Can another thread acquire lock on other synchronized block?
What will happen if a method call happened within a synchronized block to a nonsynchronized method? will that method be thread safe?
What if we try to access a static variable from a synchronized instance method?? At a time each thread accessing a synchronized block in each instance will try to modify the static variable. Is n't it? In this case how we can have thread safety??
Can another thread acquire lock on other synchronized block?
No, only one synchronized method at a time can run. A call to the other synchronized method will have to wait until the first method is done. This is described in the Java tutorials:
...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.
What will happen if a method call happened within a synchronized block to a nonsynchronized method? will that method be thread safe?
If the non-synchronized method is only called from synchronized methods belonging to this Object, then it can be considered thread-safe, since only one thread can execute one of the calling (synchronized) methods at a time.
Note that, as #Ordous points out below, static synchronized methods lock on the class, and non-static synchronized methods lock on the instance. Therefore a non-static method can interleave with a static method belonging to the class in question.
No, any other thread will not be able execute another block which acquires lock on the same object in your case args.
No. the other method which is being called from synchronized code block will not be thread safe. It can be called by any other thread from any other code block if it does not have synchronized keyword, because the thread need not to acquire any lock to execute that method.
This is common misunderstanding that synchronized keyword locks piece of code.
What synchronized keyword does?
It locks the object and not the method. So if you put synchronized keyword in front of a method then it will lock this object. so any other method with synchronized keyword can not be executed by any other thread.
This is not the same with static and not static method because when you have synchronized static method then the it will not lock this but it will lock default class object i.e A.class object. If you have another static sync method then that will not be executed by any other thread.
In case of sync blocks it will acquire lock on the object which is passed as argument in your case it is args.
so if there is another sync block anywhere else which acquires lock on the same object then it will have to wait until the first thread completes and releases the lock.
There is always a lock present on synchronised code. To access the code threads have to acquire the key , unlock , run and then handback the key.
There is a object level lock present , the lock is of the entire object and not of some method or block. So even if there are multiple synchronized block or methods on a single instance only one of the threads can acquire the key and access the synchronized code. It will then hand back the key to the object and then other threads can resume to acquire key and access synchronized code.
Incase you are wondering what happens to the static methods declared syncrhonized (since they have no objects/instances associated with them), in that case there is always also a lock present with the class itself. To access any synchronized static part of a class, a thread has to acquire the key from the class to unlock the lock.
Note:- the lock and key thing I mentioned is just to help understand, there is no methods or way to access keys or anything it is all internally maintained by JVM.
First and foremost, there can be multiple synchronized methods in a class. That is done by:
declaring the methods as synchronized
synchronized methods .
As per your question, if the threads are of the same class(multiple threads requesting the same resource, then no two objects of the same class can access a particular resource at the same time(concurrently). The thread that is holding the mutually exclusive lock(mutex) is in the monitor. All other such threads has to undergo waiting for the monitor.
Java Thread Scheduler ensures that any of the synchronized method might be required by the thread which is currently in the monitor, i.e. the one which is holding the lock. So, does not allow other threads to execute them concurrently.
That is not the case with non-synchronized methods, they can execute concurrently.

Java object locking: Deadlock when calling other methods?

If I use synchronize(this) in two methods and one calls the other, will I get stuck in a deadlock situation or will it work because the thread already owns the lock?
Picture the class below:
public class Test {
public void foo() {
synchronize(this) {
bar();
}
}
public void bar() {
synchronize(this) {
// do something
}
}
}
As you can see, there are two methods foo and bar, which both rely on synchronization.
When calling foo(), a lock will be obtained on (this); will bar try to do the same when called by foo (and thus causing a deadlock) or will it realize that the lock has already been obtained by the same thread?
Hope my explanation is more or less clear ;-)
The synchronized block is reentrant (in fact, Java monitors are reentrant, to be perfectly clear), thus no deadlock can happen in your situation.
According to the docs:
Recall that a thread cannot acquire a lock owned by another thread.
But a thread can acquire a lock that it already owns.
If thread holds lock of object it can enter to other synchronized blocks based on that lock object.
Here you can read that
"...thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block."
One thing to be careful of though is if:
Thread A has the lock in foo() and needs to call bar()
and Thread B has the lock in bar() while needing to call foo()

A question on Java multi-threading

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.
When t1 is in midway of accessing method1(). Now t2 is trying to access method2().
When t1 is in midway of accessing method2(). Now t2 is trying to access method1().
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
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
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.
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.
t2 will be allowed to start executing the method. When it hits the synchronized line, it will wait for t1 to finish method1 and release its lock before continuing.
t2 will be allowed to start executing the method so long as t1 is not within the 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.
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.
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
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.

Java synchronized question

I'm new to Java Threads and synchronization.
Lets say I have:
public class MyClass(){
public synchronized void method1(){
//call method2();
}
public synchronized void method2(){};
}
What does it mean when I synchronize a method1() on an instance object? So when a thread acquired the lock when trying to access the synchronized method1(), does it prevent other threads to access another synchronized method2() from that same object?
Lets say a thread acquires a lock when accessing method1(), but lets say that method1() makes a call to method2() which is also synchronized. Can this be possible? I mean are there any rules that can prevent method1() from calling method2()?
Thanks in advance.
Yes, using the synchronized method modifier on a non-static method means that it uses the monitor of the instance the method is invoked on, and this is shared between all such methods.
No - the thread already owns the monitor, so it is free to enter other blocks protected by the same monitor.
See here:
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.
Since this thread holds the lock on the current object, it can invoke method2(), and no other thread can.
A note on question 2, method1() can also call synchronized methods also in other classes which could cause a deadlock:
Thread1 calls synchronized method1() which in turn needs to call synchronized method_b() in AnotherClass
Thread2 holds the lock on AnotherClass and is executing a method that needs to call method1() in the class whose lock is held by Thread1
Both Threads will block waiting for the other to free the lock, a deadlock.
(1) This is equivalent to:
public void method1(){
synchronized (this) {
...
}
}
So it synchronizes on the current instance. If we rewrite method2 in the same way...
public void method2(){
synchronized (this) {
...
}
}
... then you can clearly see that they lock on the same object and thus other threads could not call method1 or method2 until method1 exits its synchronized block.
(2) synchronized blocks are re-entrant, meaning that the same thread can enter other synchronized blocks that lock on the same object as many times as it wants. As I understand it, every time you enter a synchronized block, Java increases a counter on the object you are synchronizing on by 1, and every time you exit a synchronized block, it decreases it. When that counter reaches 0, the lock is released.

Categories