acquiring the lock of another object on a synchronized block - java

i'm currently studying the multithreading concept thoroughly and i'v noticed that whenever a synchronized block is discussed, the lock on this object is acquired. e.g:
synchronized(this) {}
but, is there any reason to give another object as the argument for synchronized? or is it an inadvisable pattern?

An example why locking on something else might be beneficial:
final List<Object1> firstList = new List<>();
final List<Object2> secondList = new List<>();
// ...
public Object readFromListOne() {
synchronized(firstList) {
return firstList.remove(0);
}
}
public Object readFromListTwo() {
synchronized(secondList) {
return secondList.remove(0);
}
}
Here threads can access both lists simultaneously, while a synchronized(this) would have locked both calls, even though it isn't necessary.
Btw: a concurrent list will render all this synchronization obsolete

You can use a third party object as a lock. Generally such objects can be used to achieve synchronization to shared resources between different objects, which will be forced to acquire this third party object lock before executing certain piece of code.

You can use a common object as follows.
static final Object lock=new Object();
Then you can parse this into synchronized block as follows
synchronized(lock){
}
Only requirement here is you have to share common object. Then each path(different object) locked based on this object.
I think you are having issue with why we use other object.
If we want to locked different path by different Threads we have to locked each path. So we have to use third object. Then when one object quires that lock object other threads has to wait until that lock is resealed. But same thread which acquire the lock can continue.

synchronized(this) {}
That means that any other thread that synchronizes on this will have to release/wait until you release/wait the lock before it can proceed.
synchronized(somethingElse) {}
That means the lock happens on now with somethingElse.
So there is a clear difference and depends on what you are synchronized.

Related

What object is the lock on when a String parameter is used for locking?

I came across code like this in one of the repos. I checked it out and it works. (Only one thread enters the synchronized block.)
public Void hello(String s) {
synchronized (s) {
i++;
System.out.println(i);
}
return null;
}
My question is is the lock obtained on the String class itself? If yes, wouldn't it mean if code like this exists else where in the code base, they will all wait to obtain a lock on the same object? Thus adding unnecessary delays?
The intrinsic lock on the String object is the lock that gets acquired. But whether locking works depends on if the string is always the same instance or not. String pools and interning will affect this.
That it is difficult to figure out if the same instance will be used is only one reason not to do this.
If two classes in the application use the same string instance then one of them can acquire the lock and shut the other out. So you can have conceptually unrelated objects affecting each other, contending for the same lock.
Also people are going to be confused into thinking they can use the string value to mean something and have code change the value of s inside the synchronized block or method. That will break all the locking. Locks are on the objects, not on the variables. Changing values means the thread currently holding the lock now has the old object but threads trying to get in are trying to get the lock on the new object, a thread can acquire the new object and start executing the synchronized code before the previous thread is done.
It might work by accident sometimes but it is a terrible idea. Use a dedicated object as a lock instead:
private final Object lock = new Object();

How is this lock useful anyway?

I am relatively new to concurrency. I am practicing concurrency from Oracle website. I am stucked at the following example:-
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
I want to know how is this type of lock useful over using synchronized(this) type lock? And in which situations should this type of lock be preferred?
Thanks
It's useful when you have a single object that needs a finer resolution of exclusion than the object itself. In other words, an object with multiple resources that need to be protected but not necessarily from each other.
Being bought up in the pthreads world, this is easy to understand since the mutex and it's protected resource tended to be always decoupled - there was never this handy shorthand found in Java for using an object as the lock.
As an example, say each object has a array of a thousand integers and you want to lock a group of a hundred at a time (0xx, 1xx, and so on) for maximum concurrency.
In that case, you create ten objects, one per group of a hundred, and you can lock individual parts of the array. That way, if you have a thread fiddling about with the 0xx and 4xx blocks, it won't stop another thread from coming in and doing something with the 7xx block.
Now that's a pretty contrived example but the concept does occasionally show up in reality.
In the specific example you've given, only one thread at a time can come in and increment c1 concurrently, but a lock on lock1 still permits another thread to come in and change c2.
With a object (this) lock, concurrency would be reduced because c1 and c2 couldn't be updated concurrently despite the fact that there is no conflict.
Object lock is nothing but you are locking the critical section explicitly by an object. synchronized (this) describes that you are locking the critical section by the current object.
Having two separate locks for inc1 and inc2 is useful in situations where you want to make sure that no two concurrent threads can both call the same method at the same time, but where you do want to allow two concurrent threads to call different methods on the same object.
In your example, if thread 1 calls inc1, thread 2 is blocked from calling inc1 until thread 1 is done. However, thread 2 is free to call inc2.

Does synchronizing on a thread safe object block other calls that might manipulate it?

Suppose I create a thread safe object:
PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>();
If I synchronize on it:
synchronized (safeQueue) {
....
}
Does code that block:
// some non-synchronized block
Object value = safeQueue.poll();
No. The only time you get any blocking is if another thread is also doing a synchronized on the same object. If your code is synchronized (safeQueue) then a call to PriorityBlockingQueue.poll() would only block if poll() was a synchronized method or if the code used synchronized (this) code.
When you call safeQueue.poll() the PriorityBlockingQueue code is actually using an internal ReentrantLock, and not doing a synchronized (this). Here's the code for poll():
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return q.poll();
} finally {
lock.unlock();
}
}
Lastly, as you mention, PriorityBlockingQueue is already reentrant so you do not need to synchronize on it to allow multiple threads to access the queue. You could still need to synchronize on it if you needed to solve race conditions in your own code of course.
The short answer is: it depends on where the thread-safe class's thread safety comes from.
You have to depend on the class's documentation, or its implementation code if you want to go down that route (beware of changes in future versions...), or be defensive and not trust it, instead synchronizing on another object for your atomicity needs (or whatever else you're synchronizing for).
It certainly doesn't have to block, especially as many of the java.util.concurrent classes are non-blocking (and thus don't synchronize on themselves to achieve thread safety). On the other hand, if the class gets its thread safety from synchronized(this) (or, equivalently, synchronized instance methods), then yes, that'll block. An example of this is the map returned from Collections.synchronizedMap, in which that blocking is documented and is actually an intended feature (so that you can atomically query and modify the map).
It is possible if the object itself has methods that are synchronized on the instance. For example:
MyClass c = new MyClass();
synchronized(c) {
...
}
and MyClass is:
class MyClass {
// foo needs a lock on this
public synchronized void foo() {
...
}
}
Now, a call to c.foo(); outside of a synchronized section will still block if it's executed in parallel with the code written above.
For example, the old Java Vector class was synchronized internally like this, so locking on the object from the outside could interfere with the internal locking.

Using synchronized block

What is the difference or impact between using the synchronized block as in method1 and method2?
class A
{
private Object lock = new Object();
...
...
private void method1()
{
synchronized(A.class)
{
.....
}
}
private void method2()
{
synchronized(lock)
{
....
}
}
}
In first method all threads that use ANY instance of the class A will be syncronised.
In second method all threads that use THIS instance of the class A will be syncronised.
Since A.class is avaliable to others, it is public in effect. If something else uses it to synchronize access to some section of code then your section of code could be blocked. This might be good or bad; but you don't have control over it.
Using an internal object allows you to decare it as private so that you have complete control over where and when it is used. I prefer to use an internal object that I have control.
Lock is an ordinary field. So there is one of it for each instance of 'A'. A.class is global to the whole JVM. So the two blocks have completely different semantics. The version with 'lock' says, 'only one thread can be in this block for this instance of A'. The version with A.class says 'only one thread can be in this block for any instance of A.
In the first case, you synchronize on a public object (A.class), and so other parts of the application might cause problems because they also synchronize on A.class.
In the second case, you synchronize on a private lock object, and are thus sure that nobody else uses the the lock to synchronize access to something else.
Moreover, as indicated in other answers, all the instances of the class will be synchronized on the same lock with the first solution, whereas each instance will have its own lock with the second solution.
The second solution is thus much preferred (although the lock object should be final).
The parameter of synchronized block is needed to be able to create several "named" blocks. So using special lock object is probably more flexible: you can create lock1 and lock2 in future.
Yet another aspect is waiting and notification. You can say lock.wait() and then lock.notfify() from another thread. In this case you can also use both ways (special lock object or A.class as a lock).

Synchronized threads and locking

Can someone please explain the difference between these two examples in the context of object locking:
public void method1(){
synchronized(this){
....
}
}
And
StringBuffer aStringBufferObject = new StringBuffer("A");
public void method2(){
synchronized(aStringBufferObject){
....
}
}
I know the first example will obtain a lock on the this instance and the second will obtain a lock of the aStringBufferObject instance. But i dont really understand what the effect or the difference of the two is.
For example, in the second example, will threads still be able to execute the code inside the synchronized block because the lock is not related to the 'this' instance?
I know that synchronizing a method or a block of code prevents multiple threads to access that block/method at the same time but what is the purpose of specifying the object to lock on and what is the difference in the way the object is specified as in the above examples?
What is the purpose of specifying the object to lock on?
Often, it is easier to synchronize on this or on the Class instance (for static methods). But, there are cases where you will need to synchronize on a specific object instead of the implicit lock (this). Such cases include:
You want to synchronize access to primitives without using this. You can only synchronize on Objects as each Object is associated with an implicit monitor in Java. Primitives do not have such implicit monitors, and therefore you need to use a lock object. Using the wrapper classes are a poor and incorrect choice, especially if you end up modifying the lock object in the guarded block.
You want to synchronize on an object that actually protects the critical section, when synchronizing on this would not offer a guarantee of thread safety. For instance, if you are synchronizing access to a ArrayList instance shared across instances of class A, then synchronizing on an instance of A is useless. A thread might create a new instance of A and gain access to the list, while another thread is modifying it. If you use a different lock that all threads must contend for then you can protect the list; this lock could be the one associated with A.class, but it could be any object that will offer the same guarantees.
You want to perform lock splitting to ensure that different guarded blocks are protected by different locks instead of the same lock. In other words, if it is thread-safe to allow different threads to acquire different locks to access different critical sections, then you can have a different lock for every critical section.
The following is an example of split lock usage:
private Object method1Lock = new Object();
private Object method2Lock = new Object();
public void method1(){
synchronized(method1Lock){
....
}
}
public void method2(){
synchronized(method2Lock){
....
}
}
You would use split locks when you can ensure that the concurrent execution of method1 and method2 do not violate the class invariants. This way, you can improve performance across threads that need access to the same object, but will be invoking different methods.
On your other question,
For example, in the second example, will threads still be able to execute the code inside the synchronized block because the lock is not related to the 'this' instance?
In the second example, any thread entering the guarded region must acquire the lock associated with aStringBufferObject. If a different thread is holding that lock, then the current thread will not proceed further. When you specify this, then the thread must acquire the lock associated with the current object. In both cases, a thread must acquire a lock; the examples are only different in the object that is being used as a lock.
Synchronizing on an object means that other blocks which synchronize on the same object will have to wait. For example:
public void methodA() {
synchronized(obj) {
//Do one job
}
}
public void methodB() {
synchronized(obj) {
//Do another job
}
}
If you call methodA() in one thread and then call methodB() in another thread, methodB() won't finish before methodA() finishes.
The synchronized block is a monitor, which leave out of details to lock and unlock a mutex. Because every object in Java has an internal lock(refer to source code of Object class), when use synchronized statement, the JVM will help you synchronize the critical section. You can also synchronize block yourself use ReentrantLock in package java.util.concurrent.locks.

Categories

Resources