Synchronization on object, java [duplicate] - java

This question already has answers here:
Avoid synchronized(this) in Java?
(23 answers)
Closed 7 years ago.
I am reading the Oracle tutorials about multithreading programming in Java. I don't understand why should I create a new object to sync the some part of code? For what reason does the creation of new dummy object serve?
I do understand that creating these two objects will prevent compiler from reordering the code segment guarded by the construction syncronized(lock1){}
However, I would like to know can I use any other objects (except MsLunch) in the construction syncronized(lock1){} ?
What is the motivation behind introducing such construction syncronized(lock1){} ?
Here is the piece of code, I am concerned with:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
// what is the purpose of these two objects? how do they serve as locks?
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}

First some basics:
The synchronization object is used as a key to open a door to a restricted area (the synchronization block).
As long as a thread entered this restricted area it holds the monitor (lock) so that no other thread can enter. When a thread exits the restricted area it releases the monitor and another thread can take it.
This means that each synchronization block that uses the same synchronization object will prevent other thread to enter until the monitor is available (unlocked).
For what reason does the creation of new dummy object serve?
The reason is that you should use objects that are not accessible by others objects than the ones that use them. That's why the synchronization objects are private. If they would be accessible by others, other might use them in their synchronization blocks somewhere in the application. If the synchronizcation object is e.g. public then every other object can use it. This might lead to unexpected usage and might result in deadlocks.
So you should make sure who will get a reference to the synchronization object.

The lock is accessed by the threads to check if the code is currently "in use" or if they can execute it after locking the object themselves.
You may think it could be automatic, but it has a use compilers couldn't infer : you can use the same lock to synchronize multiple code blocks, restraining the access to any of them at the same time.

In my opinion, dummy Object just represents the point of synchronization.
For synchronize different threads, you must be able to declare point of synchronization and(if it is needed) give access to this point from different parts of the code. For example:
private Object lock = new Object();
public void inc1() {
synchronized(lock) {
c1++;
}
}
public void inc2() {
synchronized(lock) {
c2++;
}
}
In this example shown the usage of same point of synchronization from different part of code.
And because Java is Object oriented language i.e. unit of language in Java is Object, we have exactly such a construction.
By the way, you can use any object in as point of synchronization. You can do even this:
public void inc1() {
synchronized(this) {
c1++;
}
}

what is the purpose of these two objects? how do they serve as locks?
As shown in your code, inc1() and inc2() can only be invoked by one thread each. This means that c1 and c2 can be increased just once per thread - but simultaneuosly by two different threads (because both threads synchronize on different objects).
If both blocks were synchronized like this synchronized(lock1), c1 and c2 could not be increased simultaneuosly.

Related

Should locks in multi threading always remain immutable?

I am trying the below code snippet which is giving expected output.But I am curious to know how many lock objects I am creating 1 or 2?
package com.practice;
class A{
String lock="";
A(String lock){
this.lock = lock;
}
A(){ }
public void printMe(int x) {
int counter = x;
synchronized (lock) {
System.out.println(++counter);
}
}
}
public class MultiThreadingPractice {
public static void main(String[] args) {
A a = new A("1");
Thread t1=new Thread(() -> {
a.printMe(1);
});
a.lock = new String();
Thread t2=new Thread(() -> {
a.printMe(1);
});
t1.start();
t2.start();
}
}
Should locks in multi threading always remain immutable? Yes.
You're using a String (any Object would do) as a lock. When you assign a new value (new String) to the lock, that means you have more than one lock instance around. It's ok as long as all threads are synchronizing on the same lock instance, but there is nothing overt in your class A code to ensure that is the case.
In your actual use in the example, you're safe. Since no thread get started until after you've finished setting the lock to the third and last instance, nothing will be trying to sync on the lock until it's stable. (3 instances: the first is the initialization to the empty String; the second is to the supplied constructor argument "1"; and the third is the explicit assignment, to a different empty String). So, though this code "works", it only works by what I refer to as "coincidence", i.e., it's not thread-safe by design.
But let's assume a case where you start each thread immediately after you construct it. This means you'd be reassigning the lock member after t1 was running but before t2 was even created.
After a while both threads will be synchronizing on the new lock instance, but for a period around the point at which you switched the lock, thread t1 could be and probably is in the synchronized(lock) { ... } clause using the old lock instance. And around that time, thread t2 could execute and attempt to synchronize on the new lock instance.
In short, you've created a timing window (race hazard) in the mechanism that you intend to use to eliminate timing windows.
You could arrange a further level of synchronization that allows you to replace the lock, but I am unable to imagine any straightforward situation where that would be necessary, useful, or sensible. Much better to allocate one lock before any contention can occur and then stick to that one lock.
P.S. "How many locks am I creating?" 3. Though the first two are never used.
curious to know how many lock objects I am creating 1 or 2?
This line in your program creates a single String instance when the program is loaded, and both of your A instances start out with a reference to the same String.
String lock="";
This line creates a second String instance, because new String(...) always creates a new object, regardless of whether or not some other String with the same value has been interned.
a.lock = new String();
Should locks in multi threading always remain immutable? No.
The typical way to synchronize is to use synchronized methods, not separate locks. This approach is less error-prone and therefore preferred. It is equivalent to use current object as lock:
synchronized(this) {
...
}
and since this object is not usually immutable, we can conclude that using mutable objects as locks is a common practice.
What you are doing in your code, when you change the reference to the lock object (yes, you are changing the reference and not the lock object itself), is a very bad approach. It provokes programming errors.

Why do we need to pass arguments in Synchronized Statements in java? [duplicate]

This question already has answers here:
What is the purpose of passing parameter to synchronized block?
(3 answers)
Closed 5 years ago.
I was reading about synchronization concept in java and came across synchronized statements .
I want to know , why do we pass arguments to it , though it appears like static block(it's just an example) , and the arguments passed do not have any data type specified with it .
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++;
}
}
}
If any one knows about it , please explain .
In a multithreaded application when you want the states of an object to be read and written in a synchronized way by multiple threads then you use synchronized keyword.
The mechanism that Java uses to support synchronization is the monitor. Each object has a monitor associated with it. Synchronized block needs an object to work with, so that the threads in competition can compete and the winner thread can aquire the monitor.
Each non static method in java has an implicit this object upon which the particular method is invoked. If you use synchronized keyword in the method signature then it means you are depending upon the implicit this object for synchronization. If you wish to depend upon any other object then you can use the synchronized blocks and use the object reference in it.
Remember there may be various synchronized blocks but the blocks with synchronized block on same object will only gurantee the proper syncronized execution with respect to each other. Synchronized Blocks which have references of different objects do not force threads to work in synchronized way.
Thus Suppose when there is some threadA which modifies some states of an objectX and works with synchronized block with ObjectA. There may be another piece of code may be in some other class where some other threadB may be reading the states of the same objectX. Now threadB should also do the reading within a synchronized block with ObjectA so that states of objectX are read properly.

Using synchronized blocks for different methods in the same class

I was reading on official tutorial on multithreading from oracle and I came cross this example (assuming c1 and c2 are never used together):
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++;
}
}
}
}
It is said that by using lock 1 & lock 2, it helps to reduce unnecessary blocking as compare to using the word this in the synchronized block.
However, I don't really see how this helps to reduce blocking as they have no dependency on each other. I have multiple threads each running these two methods at the same time and the performance is rather similar when I use the lock objects and this keyword.
Can someone help to explain my confusion here? Love to see the explanation with an example to illustrate the difference clearly.
Adding on to the discussion here, this post helped to clarify my doubts as well. Key point: Putting synchronized on a method means the thread has to acquire the lock on the object instance before entering that method
You are using two different locks - one to protect inc1 and a different one to protect inc2. This means that thread X can run inc1 while another thread is running inc2. Had they used the same lock (regardless whether it's this or a different lock object), you would not be able to run them both concurrently. Thus, in theory at least, having two different locks should increase your performance in this scenario.

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.

Is there reasoning behind choosing a specific object?

Is the locking object used for synchronization arbitrary or is there reasoning behind choosing a specific object?
Why would you lock an object? Because it is shared among various threads. That's all there is. How you implement locking and threading is probably the difficult part, as opposed to choosing which object to lock on.
You'd be better off using one of the more modern locking techniques where much of the complexity and pitfalls have been removed/smoothed over. Package java.util.concurrent.locks would be a good start.
Your question is rather unclear.
You may be referring to a Semaphore object as a lock. You may also be referring to synchronized objects.
1) A semaphore may as well arbitrary object. It's intended purpose is that it can be used to hold threads at the semaphore until other threads release it.
2) Synchronized objects make all of their functions atomic: If a thread is operating on the object, the other object waits to complete its own function. This is usually implemented using a semaphore internally.
Semaphores are the objects used to solve synchronization problems.
The locking object needs to represent the exclusive part.
if you lock the whole object meaning using it exclusively by an thread, you may use the object "this" to lock. This is the way "synchronize" work on methods work.
public class A
{
public synchronized void do1 ()
{
...
}
public synchronized void do2 ()
{
...
}
}
if your object just has some set of members which should be used exclusively, you need separate (explicit) locking objects
public class B
{
private X x;
private Y y;
private Object lockXY = new Object ();
private R r;
private S s;
private Object lockRS = new Object ();
public void do1 ()
{
synchronize (lockXY) {
}
...
}
public void do2 ()
{
synchronize (lockRS) {
}
}
}
Beware to make locking to complex, you may run into dead locks
As in the accepted answer, the object you choose is arbitrary, just make sure you use it correctly. However, some objects are better than others. It's best practice not to use some object that may be accessible outside the context of the locking - if it is some other piece of code may also decide to synchronize on it, or call notify on it or whatever. So preferably use java.util.concurrent instead, or use private objects.

Categories

Resources