In order to properly understand the issues and solutions for concurrency in Java, I was going through the official Java tutorial. In one of the pages they defined Intrinsic Locks and Synchronization link. In this page, they say that:
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.
Also, they mention in the section Locks In Synchronized Methods that:
When a thread invokes a synchronized method, it automatically acquires
the intrinsic lock for that method's object and releases it when the
method returns. The lock release occurs even if the return was caused
by an uncaught exception.
For me this means that once I call a synchronized method from one of the threads, I will have hold of the intrinsic lock of the thread and since
Intrinsic locks play a role in both aspects of synchronization:
enforcing exclusive access to an object's state and establishing
happens-before relationships that are essential to visibility.
would another thread be unable to call another synchronized method of the same class? If yes, then the whole purpose of having synchronized methods is defeated. Isn't it?
Seems you have one misunderstanding (dunno if it caused the wrong conclusion) that no one has pointed out. Anyway, a brief answer:
Intrinsic Lock: Just think it as, every object in JVM has internally a lock. synchronized keywords tries to acquire the lock of the target object. Whenever you synchronized (a) { doSomething; }, what actually happens is
the lock in a is acquired
code within the synchronized block is run (doSomething)
release the lock in a
and I wish you know
public synchronized void foo() {
doSomething;
}
is conceptually the same as
public void foo() {
synchronized(this) {
doSomething;
}
}
Ok, go back to your question, the biggest problem, imho, is :
For me this means that once I call a synchronized method from one of the threads, I will have hold of the intrinsic lock of the thread and since...
It is wrong. When you call a synchronized method, you are not get hold of the lock of the thread.
Instead, that thread will own the intrinsic lock of the object that is "owning" the method.
e.g. in thread1, you called a.foo(), and assume foo() is synchronized. thread1 is going to acquire the intrinsic lock of the object a referring.
Similarly, if AClass.bar() is called (and bar is synchronized and a static method), the intrinsic lock of AClass Class object will be acquired.
So just to repeat my comment above as an answer. Intrinsic locking means that you don't have to create an object to synchronize your methods on. In comparison you can use an extrinsic lock by calling synchronized(myLock) {...}.
This is an excerpt from the book Java Concurrency in Practice: "The fact that every object has a built-in lock is just a convenience so that you needn't explicitly create lock objects"
The book also says:
There is no inherent relationship between an object's intrinsic lock
and its state; an object's fields need not be guarded by its intrinsic
lock, though this is a perfectly valid locking convention that is used
by many classes. Acquiring the lock associated with an object does not
prevent other threads from accessing that objectthe only thing that
acquiring a lock prevents any other thread from doing is acquiring
that same lock. The fact that every object has a built-in lock is just
a convenience so that you needn't explicitly create lock objects. [9]
It is up to you to construct locking protocols or synchronization
policies that let you access shared state safely, and to use them
consistently throughout your program.
But in the footnote it says:
[9] In retrospect, this design decision was probably a bad one: not
only can it be confusing, but it forces JVM implementors to make
tradeoffs between object size and locking performance.
And to answer your last questions: you won't be able to call the synchronized methods from another thread, but you can keep entering from the same thread (intrinsic locks are re-entrant). So you have to imagine locking in this case as serializing method access from different caller threads.
If you use locking improperly and then you introduce liveness hazards, then yes it is defeated. That's why you have to make sure that your concurrent threads are not contending with each other too hard.
As Brian Goetz puts in this blog entry:
In tuning an application's use of synchronization, then, we should try
hard to reduce the amount of actual contention, rather than simply try
to avoid using synchronization at all
A lock can be held by only one thread at a time. That doesn't defeat the purpose; that is the purpose.
Threads mutually exclude each other from simultaneous action in critical sections by acquiring a lock, or mutex. This provides effective atomicity around a series of distinct actions, so that other threads never see intermediate states that might violate consistency guarantees.
Yes, you won't be able to call other synchronized method on the same object, because of the intrinsic lock. Which is at object level, only 1 thread will acquire it.
would I be unable to call another synchronized method of the same class? If yes, then the whole purpose of having synchronized methods is defeated. Isn't it?
No. You can't call other synchronized method on same object for Object level lock and you can't call other static sysnchronized method on same class.
But it does not defeat the purpose of having synchronisation.
If you follow the other documentation page on synchronized methods:
Making these methods synchronized has two effects:
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.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
If you allow two synchronized method to run in parallel. you will bound to get memory inconsistency errors on shared data.
On a different note, Lock provides better alternative synchronized construct.
Related SE question:
Synchronization vs Lock
It doesn't matter whether the synchronized method belongs to the same class or not, what matters is if the caller thread of the method acquires the lock or not, if it does, then it will be allowed enter the critical section because the lock is reentrant.
If it wasn't the case, then a recursive call would cause a deadlock,
fn(){
synchronized(mutex){ // the current thread has already acquired the mutex
fn();
}
}
fn here wont deadlock because the lock is re-entrant, ie ( the thread that's already acquiring the lock can enter and renter the critical section again as long as it is still acquired).
Locks can be divided in two classes - 'reentrant' and 'not reentrant'.
In Java 'synchronized', base implementation of interface Lock (class ReentrantLock), interface ReadWriteLock (class ReentrantReadWriteLock) - are reentrant.
Reentrancy means - one thread can again and again hold the lock.
Related
I have been going through Java multi-threading concepts. The more I go through them, the more confused I become.
Right now I am not understanding the differences between class level, object level, explicit and intrinsic locking in Java. Can someone please let me know which is what? Also, if I can get some examples to understand, that will be very helpful for me.
Explicit vs Intrinsic
When you use synchronized on an object or indirectly as part of a method signature you are creating an intrinsic lock. You rely upon the in-built lock associated with all objects and classes.
An explicit lock is provided in Java 5+ in the package java.util.concurrent.locks. The most commonly used class is probably ReentrantLock. These provide alternatives to using the intrinsic locks and offer features that are not possible with intrinsic locks.
Class Level vs Object Level
This distinction applies to intrinsic locks only. If you have a synchronized static method, the intrinsic lock used will be associated with the class object itself. If you synchronize on an object instance (or have a synchronized instance method) it will be an object-level lock.
Further Reading
Brian Goetz's Java Concurrency in Practice is an excellent book for understanding the nightmarishly confusing world of multi-threaded programming in Java.
When you use "Synchronized" keyword, it uses intrinsic locks or monitors. Every object in Java has an intrinsic lock associated with it. Whenever a thread tries to access a synchronized block or method, it acquires the intrinsic lock or the monitor on that object or Object level Lock. In case of static methods, the thread acquires the lock over the class object.
public synchronized void doAtomicTransfer(){
//enter synchronized block , acquire lock over this object.
operation1()
operation2();
} // exiting synchronized block, release lock over this object.
An intrinsic locking mechanism can have some functional limitations, such as:
It is not possible to interrupt a thread waiting to acquire a lock (lock Interruptibly).
It is not possible to attempt to acquire a lock without being willing to wait for it forever (try lock). Only one thread can hold the lock at once: there's no facility, for example, to allow multiple threads holding a lock simultaneously for read-only access.
Cannot implement non-block-structured locking disciplines, as intrinsic locks must be released in the same block in which they are acquired.
Explicit locks are useful in cases where you need to overcome some of the shortcomings of built-in synchronization. In particular, they have the following features:
A thread can attempt to acquire a lock interruptibly;
A thread can give a timeout value for attempting to acquire the lock;
Read/write locks are supported– that is, locks that allow multiple concurrent readers if the lock is not locked for writing;
The traditional wait/notify metaphor is extended to allow conditions (see below);
Support for fairness (if more than one thread is waiting for a lock, they acquire in first-in-first-out order when it becomes available);
The ability to lock beyond the scope of a block: for example, one method can pass a lock object to another thread;
Locks can be queried to find out, for example, if they currently have any threads waiting to acquire them.
"class-level" locking, and "object-level" locking are artificial ideas, created by authors who probably do not have a deep understanding of how Java's intrinsic locking works.
class-level locking looks like this:
class Foobar {
static synchronized void moo() { ... }
}
But that construct actually is just a shorthand way of writing:
class Foobar {
static void moo() {
synchronized (Foobar.class) { ... }
}
}
And object-level locking, which looks like this:
class Foobar {
synchronized void baa() { ... }
}
Is nothing but shorthand for:
class Foobar {
static void baa() {
synchronized (this) { ... }
}
}
So really, underneath "class-level" and "object-level" locking, there is only one concept, the synchronized block:
synchronized(objectReference) {...}
All you need to know is that the JVM will not allow more than one thread to synchronize on the same object at the same time.
When data that you want to protect are global, then it makes sense to synchronize on a global, singleton object while accessing the data. Foobar.class is a global singleton.
When data that you want to protect are entirely contained within some object instance, then it makes sense to synchronize on something associated with that instance or, on the instance itself (i.e., this).
I have read different things in different blogs about monitors. So I'm a bit confused now.
As much as I understand, monitor is a somebody who would make sure that only one thread is executing the code in the critical section. So is it like if we have 3 synchronized methods/blocks then we would have 3 monitors to make sure that only one thread is in the critical section?
If the above is true then why it is said that in Java every object has a monitor associated with it? It should be every synchronized block is associated with a monitor.
What is a monitor?
A monitor is something a thread can grab and hold, preventing all other threads from grabbing that same monitor and forcing them to wait until the monitor is released. This is what a synchronized block does.
Where do these monitors come from in the first place?
The answer is: from any Java object. When you write:
Object foo = new Object();
synchronized (foo) {
System.out.println("Hello world.");
}
...what this means is: the current thread will first grab the monitor associated with the object stored in variable foo and hold it while it prints "Hello world", then releases it.
Why does every Java object have a monitor associated with it?
There is no technical reason for it to be that way. It was a design decision made in the early versions of Java and it's too late to change now (even though it is confusing at first and it does cause problems if people aren't careful).
When using synchronized with blocks, you specify an object to lock on. In that case, the monitor of that object is used for locking.
When using synchronized with methods, you don't specify an object to lock on, and instead this object is implied. Again, the monitor of this is used for locking.
So, objects have monitors, and synchronized methods/blocks do not have their own monitors, but instead they use the monitors of specific objects.
In the context of Java programming, the monitor is the intrinsic lock (where intrinsic means "built-in") on a Java object. For a thread to enter any synchronized instance method on an object it must first acquire the intrinsic lock on that object. For a thread to enter any synchronized static method on a class it must first acquire the intrinsic lock on that class.
This is how monitor is defined in the Java tutorial:
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.")
There is a good reason that the monitor belongs to an object, and not to an individual block: the monitor is there to protect the state of the object. Objects should be designed to be cohesive, making it likely that instance variables will end up being referenced by multiple methods; the safe thing to do, in order to guarantee that the object is always in a consistent state, is to allow only one synchronized method on that object to execute at a time.
The term "monitor" comes from Concurrent Pascal. See Per Brinch Hansen's paper "Java's Insecure Parallelism", which argues that Java doesn't actually implement monitors:
Gosling (1996, p. 399) claims that Java uses monitors to synchronize threads. Unfortunately, a closer inspection reveals that Java does not support a monitor concept:
Unless they are declared as synchronized, Java class methods are unsynchronized.
Unless they are declared as private, Java class variables are public (within a package)
Another quote from the same paper:
The failure to give an adequate meaning to thread interaction is a very deep flaw of Java that vitiates the conceptual integrity of the monitor concept.
As per my understanding, if we add synchronized keyword in our code, whole block of code inside it will be locked for the other threads. In that case, why do we need to specify a particular object in synchronized keyword.
for eg. synchronized(lockObject). what is the use of lockObject here?
Let's say you have 2 resources you want to synchronize; the bathroom and the fridge.
You want people to be able to grab a snack from the fridge even if someone is using the bathroom, don't you?
So you use different locks on the fridge and on the bathroom.
In programming terms, that means that each independent resource can have it's own lockObject.
Note that a resource can have several methods that access them - all the accessors of the same resource should use the same lock! After all, if you have two doors into the bathroom it wouldn't do much good if you only locked one of them.
if we add synchronized keyword in our code, whole block of code inside it will be locked for the other threads.
Incorrect. synchronized involves a mechanism entirely separate from your block of code: acquiring and releasing a mutual exclusion lock. Java has the concept of synchronized blocks as a convenience to ensure proper release of a lock after it's acquired.
So, what actually happens is that your thread acquires the monitor associated with the instance given in the parentheses, then proceeds to execute the block of code, then releases the monitor. Meanwhile no other thread can acquire that particular monitor, but it can very well acquire any other object's monitor. If you don't take care to always have the same object involved in the synchronized block, you will get no mutual exclusion.
What actually happens when the same thread tries to acquire a lock that it already owns ?
I guess your question is about the semantics of the synchronized block/modifier. Refer to the Java Language Specification. If your question is about a specific implementation's way of doing it, then you need to specify the exact implementation you have in mind. But this being a well-understood technique, I don't see a reason for that.
Quoting from http://download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/locks/ReentrantLock.html
A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit >monitor lock accessed using synchronized methods and statements, but with extended >capabilities.
A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. >A thread invoking lock will return, successfully acquiring the lock, when the lock is not >owned by another thread. The method will return immediately if the current thread already >owns the lock. This can be checked using methods isHeldByCurrentThread(), and getHoldCount().
I Agree that GrepCode explains it very well
This question already has an answer here:
What's the difference in using ReentrentLock and Synchronized(object)? [duplicate]
(1 answer)
Closed 5 years ago.
I have used the synchronized keyword and re-entrant locks in Java, but I don't understand how they differ, or which is appropriate for a given situation.
How do I decide when should I use synchronized and when I should use re-entrant locks?
A ReentrantLock is:
A reentrant mutual exclusion Lock with the same basic behavior and
semantics as the implicit monitor lock accessed using synchronized
methods and statements, but with extended capabilities.
Extended capabilities include:
The ability to have more than one condition variable per monitor. Monitors that use the synchronized keyword can only have one. This means reentrant locks support more than one wait()/notify() queue.
The ability to make the lock fair. Synchronized blocks are unfair.
"[fair] locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order."
The ability to check if the lock is being held.
The ability to get the list of threads waiting on the lock.
The disadvantages of reentrant locks are:
Need to add import statement.
Need to wrap lock acquisitions in a try/finally block. This makes it more ugly than the synchronized keyword.
The synchronized keyword can be put in method definitions which avoids the need for a block which reduces nesting.
Summary
The synchronized keyword is syntactically nicer, but the Reentrant lock has more features.
This site clearly mentioned difference between ReentrantLock and synchronized keyword in Java. I just copy and paste from there.
http://javarevisited.blogspot.in/2013/03/reentrantlock-example-in-java-synchronized-difference-vs-lock.html
1) Another significant difference between ReentrantLock and synchronized keyword is fairness. synchronized keyword doesn't support fairness. Any thread can acquire lock once released, no preference can be specified, on the other hand you can make ReentrantLock fair by specifying fairness property, while creating instance of ReentrantLock. Fairness property provides lock to longest waiting thread, in case of contention.
2) Second difference between synchronized and Reentrant lock is tryLock() method. ReentrantLock provides convenient tryLock() method, which acquires lock only if its available or not held by any other thread. This reduce blocking of thread waiting for lock in Java application.
3) One more worth noting difference between ReentrantLock and synchronized keyword in Java is, ability to interrupt Thread while waiting for Lock. In case of synchronized keyword, a thread can be blocked waiting for lock, for an indefinite period of time and there was no way to control that. ReentrantLock provides a method called lockInterruptibly(), which can be used to interrupt thread when it is waiting for lock. Similarly tryLock() with timeout can be used to timeout if lock is not available in certain time period.
4) ReentrantLock also provides convenient method to get List of all threads waiting for lock.
I have always thought of synchronization as "the hack of least resistance". It just works and most everyone understands how it works, but it has some weaknesses that could affect your design under heavy concurrency. Not least of which is any client effectively has direct access to your object's synchronization lock meaning if they grab it and hold it other clients can't. In other words, the locking implemented by default synchronization effectively "publishes" you object's internal locking mechanism. Yuk. Its like setting yourself up for self-inflicted denial-of-service.
If you make the reentrant lock internal to your class (or just don't use the synchronized but do something like synchronize on some internal object that you new up in your constructor everywhere that you want synchronization), you remove this side-effect of publishing your internal locking mechanism, with the added complexity of you having to remember where to apply this internal synchronization as your class evolves.