Consider following class that I have wrote for testing the locking of non-primitive variable (myObject). If all threads are working on same object instance of SynchronizationTest, my questions are:
I understand that if thread1 is executing set(...) method then any other thread (lets say thread2) is okay to execute either of the anotherSetWithSynchronized(...) or anotherSetWithoutSynchronized(...).
If thread1 has locked the object of SynchronizationTest while executing set(...), does it mean it has acquired lock on all member object variable ? like in this case myObject. If not then,
If thread1 is executing set(...) can thread2 execute anotherSetWithSynchronized(...) concurrently?
Are none of the two methods can execute simultaneously by thread?
Is this design wrong? Do I need to explicitly lock myObject in synchronized set(...) method. Like this:
public synchronized void set(MyValue myValue) {
synchronized (myObject) {
myObject.put(myValue);
}
}
Here's my code:
public class SynchronizationTest {
private MyObject myObject = new MyObject();
public synchronized void set(MyValue myValue) {
myObject.put(myValue);
}
public void anotherSetWithSynchronized(MyValue myValue) {
synchronized (myObject) {
myObject.put(myValue);
}
}
public void anotherSetWithoutSynchronized(MyValue myValue) {
myObject.put(myValue);
}
}
1: No, set(...) method is guarded by "SynchronizationTest" Object's lock.
2: Yes, their guard objects are different as you've designed.
3: One thread can only run one method per time. If you mean two threads, as I've explained, the methods are guarded by two objects and therefore they can be executed simultaneously
4: Yes, you're right.
The intrinsic lock in Java is described as follows in the book "Java Concurrency In Practice":
A synchronized block has two parts: a reference to an object that
will serve as the lock, and a block of code to be guarded by that
lock. A synchronized method is shorthand for a synchronized block
that spans an entire method body, and whose lock is the object on
which the method is being invoked. (Static synchronized methods use
the Class object for the lock.)
For more details, you can refer to section 2.3.1 of "Java concurrency in Practice".
synchronized method is equivalent to
public void method(){
synchronized(this){
//something
}
}
1) no
Synchronization is only on specified objects, not on its members.
2) no
3) yes, they cannot, only one thread can be active inside synchronized section guarded by given monitor
4) you don't need to (and you should not use synchronized on method level if you are using explicit synchronization). BUT its better (for libraries/large codebase), because then you can controll who can acces instance on which synchronization occurs, so someone other can't synchronize on it and cause deadlock.
Does Thread lock on object ensures lock on member objects too?
No.
I understand that if thread1 is executing set(...) method then any other thread (lets say thread2) is okay to execute either of the anotherSetWithSynchronized
Yes, unless myObject has the same value as 'this'.
Related
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.
Say I have an object A which has 2 methods:
public doSomething()
{....}
public synchronised doSomethingElse()
{ ... }
and I have thread1.doSomethingElse(), will it still be possible for thread2.doSomething() to execute or is it blocked by thread1's lock?
If so, how can I make thread1 execute at the same time?
There are two types of synchronization
1. Object level
2. Class level (Class level synchronization is for the static methods only.)
In your case since your methods are not static it is object level synchronization. For object level synchronization you can either synchronize your whole methods or you can synchronize some block of your methods.
When you synchronized one method. Its mean that same object of your class cant access your synchronized method from different threads. As each object have only one lock. If you had called doSomethingElse() for same obj but from different threads. Then It will be accessible by one thread.
Now comes to your answer:
As your first method is not synchronized i.e something(). It will not be effected in any case if you call it for any no of threads or even call it when your first thread is currently in the method. Locks are only for synchronized methods
Yourclass obj = new Yourclass();
Thread A = new MyThread(obj);
Thread B = new MyThread(obj);
......
public void run()
{
\\do what ever you want
\\both of your methods will be called.
\\ call them both here.
}
here i have made objects of same Mythread class you can do as per you want. you can make objects of two different implemented thread classes and write your run. In any case it will have no effect on the call.
Since thread 2 is not attempting to acquire any lock, it is not blocked and can run concurrently with thread 1. There's nothing special you need to do.
Assuming I have two different objects of same class, do they will able to execute the same synchronized method at the same time because the lock is on the object ant not on the method.
Example:
MyCLass cc= new MyCLass();
MyCLass cc1= new MyCLass();
Now create two thread
t1 --- it will call cc.meth
t2--it will call cc1.meth
// in this case t1 thread get lock on object cc and t2 thread get lock on object cc1.. it will work
synchronized meth(){
}
is it correct?
I think your question is answered here https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html, that tell that just one instance of the same class is locked while executing a synchronized method, obviously even if executed by a thread.
You are right. Synchronized methods lock their instance, not the class nor the method (for synchronized static methods, see below...).
So, on a given instance, only one thread can be inside any of its synchronized methods, but that does not block threads working with other instances of the same class.
Synchronized static methods lock the class (they don't have a this instance), so of all threads only one at a time can be executing inside a synchronized static method of the given class.
And if you need some other locking scheme, you can use a synchronized(someObject) { ... } block, which synchronizes on someObject, and then you are free to select the object that represents the mutual-exclusion group.
So, a synchronized method A.b() is equivalent to synchronized(this) {...} or (in the static case) synchronized(A.class) {...}.
synchronized implemented by monitorenter. You can see it in your byte code. monitorenter use the object monitor - the monitor of the instance of the class (not the class itself). So it is the expected behavior. If two threads try to execute synchronized methods of two different instances at the same time, both should not be blocked.
Actually it is better to avoid synchronized if the objects are not shared because synchronized is not good for performance. You should start thinking about synchronized only when you know that the object will be shared by more than one thread, which is not your case.
EDIT:
More simple explanation is that this code:
public synchronized void meth() {
...
}
equivalent to:
public void meth() {
synchronized (this){
...
}
}
Can you tell me if following invocations are reentrant or not?
public class Foo {
public synchronized void doSomething() {}
public synchronized void doAnotherSomething() {}
}
public class Too {
private Foo foo;
public synchronized void doToo() {
foo.doSomething();
//...other thread interfere here....
foo.doAnotherSomething();
}
}
are 2 continuous invocations in method doToo() reentrant? I'm not sure about this case since foo.doSomething() method acquire and release the intrinsic lock, no nested synchronization between 2 invocations. Is there situation that other thread might interfere between 2 invocations?
First of all, regarding reentrant locks in Java:
Synchronized blocks in Java are reentrant. This means, that if a Java thread enters a
synchronized block of code, and thereby take the lock on the monitor object the block is synchronized on, the thread can enter other Java code blocks synchronized on the same monitor object.
Taken from here.
The two consecutive calls you described (in doToo) will not be interfered unless another object has a reference to Too's private Foo, since, to access foo, one needs to lock Too. However, the calls do not invoke reentry as the locks are acquired and released for every call. They would be reentrant if doSomething called doAnotherSomething or vice versa.
That depends entirely on what other threads are accessing. Can another thread take over the CPU between those functions? Yes. Will there be a race condition? Depends on many factors.
From what you posted foo.doSomething will be locked on foo, then released, then locked again upon entry to doAnotherSomething. So if another thread not locked on the same Too object tries to manipulate foo they will be able to do so between doSomething and doAnotherSomething. If everyone synchronized on the same Too object before manipulating the underlying foo object, then those two methods of foo will not have state manipulated between calls because the Too object method will block other threads until completion. Thus if you have a problem or not depends on your other accessors.
There is no reentrance here from what you posted, but java is ok with reentrant synchronization as Amir posted.
first of all locks are applicable on objects so need to create the object and then apply the lock.
are 2 continuous invocations in method doToo() reentrant? I
In your case they are not re-entrant . if code is something like below then they will be re-entrant .
public class Foo {
public synchronized void doSomething() {
doAnotherSomething();
}
public synchronized void doAnotherSomething() {}
}
Once lock has been acquired on one object then on same object it can traverse like in above case.
If a synchronized method calls another synchronized method, is it thread safe?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Yes, when you mark methods as synchronized, then you are really doing this:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
When the thread call gets into method2 from method1, then it will ensure that it holds the lock to this, which it already has, and thus it can pass through.
Now when another thread tries to get directly into method1 or method2, then it will block until it can get the lock (this), and only then it will enter into any of the two methods.
As noted by James Black in the comments, you do have to be aware with what you do inside of the method body.
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
Suddenly it's not thread safe because you are looking at a ConcurrentModificationException in your future because method3 is unsynchronized, and thus could be called by Thread A while Thread B is working in method1.
Is a method marked with synchronized call another synchronized method thread safe.
In general, it is not possible to say. It depends on what the methods do, and what other methods on the same and other classes do.
However, we can be sure that calls to method1 and method2 on the same object made by different threads will not execute simultaneously. Depending on what the methods do, this may be sufficient to say that the class is thread-safe with respect to these methods.
From the Java Tutorials site http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
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.
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
So Java will ensure that if 2 threads are executing the same method, the methods will not executed consurrently but one after another.
But you need to be aware of the Liveness problem, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
And also whether you are locking uncessarily, cause in the code you used this, which locks the whole object, if your object only needs sync access to one variable you should just lock that variable.