Java: synchronize object inside another synchronized object - java

I am trying to get familiar with wait() and notify() methods and I have written a simple class acting like a monitor for a simple producer-consumer excercise where there are N producers and N consumers. Anyway the monitor, as requested in the excercise, can store only 3 items. So the producers must wait; on the contrary if there are 0 items in the monitor the consumers must wait.
public class Monitor {
private List<Integer> items;
private int capacity;
private Object waitProducer;
private Object waitConsumer;
private int counter;
public Monitor() {
this.items = new ArrayList<Integer>();
this.capacity = 3;
this.waitProducer = new Object();
this.waitConsumer = new Object();
this.counter = 0;
}
public void produce() throws InterruptedException {
synchronized (this) {
if (this.items.size() == this.capacity) {
synchronized (this.waitProducer) {
System.out.println("Producer " + Thread.currentThread().getId() + " aspetta");
this.waitProducer.wait(); /***/
}
}
counter++;
System.out.println("Thread " + Thread.currentThread().getId()
+ " produces object " + counter);
this.items.add(counter);
synchronized (this.waitConsumer) {
this.waitConsumer.notify();
}
}
}
public void consume() throws InterruptedException {
synchronized (this) {
if (this.items.size() == 0) {
synchronized (this.waitConsumer) {
this.waitConsumer.wait(); /***/
}
}
System.out.println("Thread " + Thread.currentThread().getId()
+ " consume object " + this.items.get(0));
this.items.remove(0);
synchronized (this.waitProducer) {
this.waitProducer.notify();
}
}
}
}
I think that there is a problem in lines with /***/: infact when the wait() method is invoked then the thread releases the lock on waitProducer (or waitConsumer) but it does not on the Monitor object. That's why when the first produces (of the first consumer) calls wait() then the Monitor object is no more obtainable. Obvioudly the access to the Monitor object must be in mutual exclusion so that to update correctly the list and the counter. So, what is the correct way? Thanks

Only one thread can execute the code inside synchronized blocks at a time.
Also, one must gain an exclusive lock on an object (via synchronized(object)) when calling wait() on that object.
This means, the unlocking/unblocking/notify code must be accessible to other threads outside of original block which called wait(). Otherwise, execution will wait forever.
In your code no other thread can reach this.waitConsumer.notify(); while one thread waits on this.waitProducer.wait();. Because all of it is also enclosed in a synchronized(this) block, other threads will keep contesting for locking on this.

#james large What do you mean that two threads can be synchronized in the same block if they are synchronized on different objects?
Suppose you have a synchronized block that looks like this:
synchronized(obj) {
...body of synchronized block...
}
...whatever happens next...
When Java thread T executes that statement, it starts by evaluating the expression, obj. That expression must either return null, or it must return a reference to an object. If it's null, then a NullPointerException will be thrown. Otherwise, thread T will attempt to lock the object.
No two threads can ever lock the same object at the same time. If the object already was locked by some other thread, then thread T will be unable to proceed until the object is unlocked.
When thread T finally is able to lock the object, it will execute the body of the synchronized block, and then it will unlock the object and move on to whatever happens next.
The important concept here is the expression, obj. Suppose that thread T evaluates obj, gets a reference to object O, locks it, and enters the synchronized block. Then thread U comes along, evaluates obj, gets a different object, P. Thread U will lock object P, and will be able to enter the synchronized block while thread T still is in there at the same time.
So how can that happen?
When it's intended, it might look like this:
class MyClass {
private final Object lock = new Object();
void foobar() {
synchronized(lock) { ... }
}
}
If thread T and thread U are operating on different instances of MyClass, then each instance will have its own lock object. Usually, in this case, the body of the synchronized block will only operate on other instance variables of MyClass. Since the two threads are operating on different data, there is no harm in them both being in the same synchronized block at the same time.
The purpose of synchronization is not to keep two threads out of the same method at the same time: The purpose is to keep two threads from operating on the same data at the same time.
Sometimes a newbie programmer writes this:
static Integer count = new Integer(0);
...
synchronized(count) {
count += 1;
...operate on static data...
}
This is almost always a mistake. When thread T enters the block, it will synchronize on the Integer object that is referenced by the static variable count. But then the next thing it does is update count to refer to a different Integer object. Then along comes thread U. U synchronizes on the new count, and both threads are in the same block, operating on the same static data when they should not.

Related

Confusion Regarding java threads on same/different objects

public class Computation extends Thread {
private int num;
private boolean isComplete;
public Computation(int nu) {
num = nu;
}
public void run() {
System.out.println("Thread Called is: " + Thread.currentThread().getName());
}
public static void main(String... args) {
Computation [] c = new Computation[4];
for (int i = 0; i < 3; i++) {
c[i] = new Computation(i);
c[i].start();
}
}
}
My Question is in main function we are creating every time a new Computation object on which the thread is being started then why we need to snchrnoized the run method? As we know for every different class object 'this' reference is different so we don't need to synchronize.
Also in another Example:
public class DiffObjSynchronized implements Runnable {
#Override
public void run() {
move(Thread.currentThread().getId());
}
public synchronized void move(long id) {
System.out.print(id + " ");
System.out.print(id + " ");
}
public static void main(String []args) {
DiffObjSynchronized a = new DiffObjSynchronized();
/**** output ****/
// 8 9 8 9
new Thread(a).start();
new Thread(new DiffObjSynchronized()).start();
}
}
Here is second example just like first we create a Thread on 2 different instances of class. Here we synchronize the move() method but by definition:
"two different objects can enter the synchronized method at the same time"
Please share your feedback?
If I understand you correctly, your question is: "Why is the move method synchronized?"
The answer is: it shouldn't be, for two reasons:
It doesn't access any fields, so there is nothing that could be corrupted by having many threads inside that method at once.
Each thread gets a different instance of the object, and thus a different lock. So the synchronized modifier makes no difference. Each thread can still enter its own instance's move method because they have separate locks.
You only need to synchronize when you have some data which is being shared between threads, and at least one thread is modifying that data.
Your threads are operating on different objects since you create a new instance for each thread. The intrinsic lock used by synchronized belongs to the instance. So the synchronized methods entered by your threads are guarded by different locks.
You need to understand how synchronization works.
Threads take a 'lock' on the object on which you are synchronizing when they enter the synchronized block. If you have a synchronized method then in that case the object becomes the 'this' instance. Now, no 2 threads can take a lock on the same object at the same time. object locks are mutex based in philosophy so only once thread can hold the mutex at a time. When the thread holding the lock exits the synchronized method or the block, it releases the mutex and thus the object lock becomes available to other threads to request lock on.
This link explains the concepts excellently. It has pictures about disassembled byte code which shows how threads take and leave locks and why 2 threads on 2 different object dont block each other.

What is the use of taking a lock on an object in synchronized block, if it can be accessed in any other method?

If there is a synchronized block which is taking lock on an object, say StringBuilder sb, which one thread is executing this synchronized block in which sb is locked, suppose there is another thread which is calling another method which will try to change the value of sb(not in synchronized block), then, will it be allowed to do that?
public static void main(String[] args) {
A a = new A();
new Thread(new MyRunnable(a), "T1").start();
new Thread(new MyRunnable(a), "T2").start();
}
static class MyRunnable implements Runnable {
A a;
public MyRunnable(A a) {
super();
this.a = a;
}
#Override
public void run() {
while (true) {
if ("T1".equals(Thread.currentThread().getName())) {
a.m1();
} else {
a.m2();
}
}
}
}
static class A {
StringBuilder abc = new StringBuilder("fdfd");
public void m1() {
synchronized (abc)
{
System.out.println("abc locked : " + abc);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();}
System.out.println("abc released: " + abc);
}
}
public void m2() {
System.out
.println(Thread.currentThread().getName() + " running");
System.out.println("trying to access abc");
abc.append("A");
System.out.println("abc accessed");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();}
}
}
}
I thought locking an object would not allow to change that object as well from being modified or accessed. But, from output I am seeing the locked object can be modified:
OUTPUT:
abc locked : fdfd
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc accessed
T2 running
trying to access abc
abc released: fdfdAA
abc accessed
abc locked : fdfdAAA
T2 running
I am not getting this, can anybody please explain this. What is the use of taking a lock on an object? Is it just because wait/notify/notifyAll methods?
If there is a synchronized block which is taking lock on an object, say StringBuilder sb, which one thread is executing this synchronized block in which sb is locked, suppose there is another thread which is calling another method which will try to change the value of sb(not in synchronized block), then, will it be allowed to do that?
Uh yes. I think you need to do some reading about what synchronized does. See the Java tutorial. It does not "lock" an object as in restrict other threads from operating on it. What it does is provide mutex for the surrounded block of code for threads that lock on the same object instance. The fields in an object are perfectly able to be mutated both inside or outside the synchronized block.
It is always a good idea to synchronize on a constant object so I tend to do something like:
private final Object lock = new Object();
...
synchronized (lock) {
// only one thread allowed inside this block at a time
}
If multiple threads are accessing some sort of thread-unsafe object, I will synchronize on that object and do the operations on the object inside the synchronized block:
private final SomeUnsafeObject someObject = ...;
...
synchronized (someObject) {
// only one thread allowed inside this block at a time
someObject.someUnsafeMethodCall(...);
}
// no accesses (read or write) outside of the synchronized block
I thought locking an object would not allow to change that object as well from being modified or accessed. But, from output I am seeing the locked object can be modified:
No, there is no implicit blocking of the object being changed. If you only access the object's fields inside of the synchronized block then you would have accomplished what you want.
public void m2() {
...
abc.append("A");
Right, since you are not inside of a synchronized (abc) block here, there is nothing that stops the thread from calling abc.append(...).
I am not getting this, can anybody please explain this. What is the use of taking a lock on an object? Is it just because wait/notify/notifyAll methods?
Synchronization allows you to control access to a block of code to one thread at a time based on the lock object (or the monitor on that object to be precise). It also allows you to do lock.wait(...) and lock.notify(...) to control the threads operation and block/release them as well.
Synchronization also puts up memory barriers so that a thread will see changes stored to central memory when it enters a synchronized block and will see it's changes written to central memory when it leaves. Without these memory barriers, if other threads access the StringBuilder without synchronization then they may seem some partially updated portion of that class which can cause NPEs or other failures.
A thread will only have to wait to access a locked code region, if that lock is held by another thread. However, it doesn't have to wait if it doesn't need a lock, i.e., your StringBuilder instance is only safe if every access is surrounded by a synchronized block locking on the same lock.
In your case, since access to abc in method m2() is not in synchronized block, a thread doesn't need a lock, and hence can access it.
When you are synchronizing on a Lock object the lock object has to be accessible by all threads, so either use a static object or a field belonging to the calling code.
Then you code will work to have only only one thread at a time accessing a certain block(s) of code. It will not prevent you acting in that code in anyway that you wish, but only one Thread can do it at one time.

Why does this throw an IllegalMonitorStateException?

I am getting into Java multithreading. I am very familiar with C/C++ pthreads, but am having issues with the Java notify() and wait() functions.
I understand that an IllegalMoinitorStateException is only thrown when a thread that doesnt "own" (aka hasnt synchronized) calls notify/wait.
When writing my application, I ran into this issue. I isolated the problem with the following test code:
public class HelloWorld
{
public static Integer notifier = 0;
public static void main(String[] args){
notifier = 100;
Thread thread = new Thread(new Runnable(){
public void run(){
synchronized (notifier){
System.out.println("Notifier is: " + notifier + " waiting");
try{
notifier.wait();
System.out.println("Awake, notifier is " + notifier);
}
catch (InterruptedException e){e.printStackTrace();}
}
}});
thread.start();
try{
Thread.sleep(1000);
}
catch (InterruptedException e){
e.printStackTrace();
}
synchronized (notifier){
notifier = 50;
System.out.println("Notifier is: " + notifier + " notifying");
notifier.notify();
}
}
}
This outputs:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at HelloWorld.main(HelloWorld.java:27)
I believe I have already acquired the lock on the notifier object. What am I doing wrong?
Thanks!
EDIT:
From this possible duplicate(Synchronizing on an Integer value), it seems that it is not a good idea to synchronize on an Integer because it is hard to make sure you are synchronizing on the same instance. Since my integer I am synchronizing on is a global visibile static integer, why am I getting different instances?
Because of notifier = 50; you are calling notifier.notify(); on a different object.
Initially when you calling synchronized on notifier in non-main Thread it was referencing to the object on heap whose content was 0 hence the thread owns that object . Now after non-main thread is put on wait using notifier.wait the control is given to the main thread . There after acquiring lock on object of Integer containing value 0 you made the notifier to refer the other object on heap memory containing value 50 because notifier = 50; is actually equivalent to notifier = new Integer(50) which means a new object of Integer is created and its reference is passed to notifier. Now , when the thread sees notifier.notify it looks that the Main thread now no longer owns the original object that it had acquired before. So IllegalMonitorStateException is throwing.
Just to add more information, you should never synchronize on a non-final object.
You need to synchronize on a constant object. If you synchronized on any object that you are assigning (i.e. changing the object) then the object is not constant and once it assigns the object and tries to notify on it, you will get the IllegalMonitorStateException. It also means that because they are synchronizing on different objects, multiple threads will be entering the protected block at the same time and race conditions will happen.
Since my integer I am synchronizing on is a global visibile static integer, why am I getting different instances?
When you assign a value to an Integer it changes it to a different object reference -- even if it is static. You are not changing the same object because Integer can't be mutated. So notifier = 50; assigns it to a different object than notifier = 0;.
If you want to use, for example, a constant object you can use an AtomicBoolean:
public static final AtomicInteger notifier = new AtomicInteger(0);
...
synchronize (notifier) {
notifier.set(50);
...
}
Here, AtomicInteger can be marked final because it's the same object all of the time.
For more information, see: Why is it not a good practice to synchronize on Boolean?

Does Java monitor include instance variables?

Is it that monitor in Java does not restrict access to instance variables and only to the methods which are declared synchronized or code in synchronized statements?
I have created two threads, thread y invokes sync() method, which is declared synchronized while thread r invokes unsync() method which is not declared synchronized. Both invoke methods on shared object s.
Thread r is able to modify the instance variable of object s while the monitor or lock of that object is still being held by the thread y.
Is it that the monitor in Java does not restrict access to instance variables, and only to the methods which are declared synchronized or code in synchronized statements?
public class Stuff {
private int a = 10;
public synchronized void sync() {
long t1 = System.currentTimeMillis();
System.out.println("Okay, I am in sync() method. "
+ "I will be waiting for 10 seconds. Current Time = "
+ System.currentTimeMillis());
while (System.currentTimeMillis() - t1 < 10000);
System.out.println("Okay, I have waited for 10 seconds. Current time is "
+ System.currentTimeMillis()
+ ". Now I will exit from sync() method, a = " + this.a);
}
public void unsync() {
System.out.println("Alright, I am in unsync() method. The current time is "
+ System.currentTimeMillis());
this.a = this.a + 1;
System.out.println(". The time of exit from unsync() method is "
+ System.currentTimeMillis());
}
}
class T1 extends Thread {
Stuff s;
public T1(Stuff s) {
this.s = s;
}
public void run() {
s.sync();
}
}
class T2 extends Thread {
Stuff s;
public T2(Stuff s) {
this.s = s;
}
public void run() {
s.unsync();
}
}
class Main {
public static void main(String args[]) throws Exception {
Stuff s = new Stuff();
T1 y = new T1(s);
T2 r = new T2(s);
y.start();
Thread.sleep(2000);
r.start();
}
}
The output of the program is below:
Okay, I am in sync() method. I will be waiting for 10 seconds. Current Time = 1358801766310
Alright, I am in unsync() method. The current time is 1358801768343. The time of exit from unsync() method is 1358801768343
Okay, I have waited for 10 seconds. Current time is 1358801776310. Now I will exit from sync() method, a = 11
Yes. Holding the monitor of an object prevents another thread from executing another block of code or synchronized on the same object. If a method is not synchronized, any thread can call it at any time, whether another thread holds a monitor or not.
Every access to a shared stated, even read-only accessed, must be synchronized if there's a chance that at least one thread modifies this shared state.
Is it that monitor in java does not restrict access to instance variables and only to the methods which are declared synchronized or code in synchronized statements?
Yes.
Synchronized blocks (or methods) are, among other things, mutually exclusive. That does not prevent the object used as a lock (the monitor, let's call it lock) to be used outside those blocks, in which case no synchronization will be performed. For example, one thread could read or write lock while another thread is within a synchronized block where lock is the monitor.
If you want to restrict access to a variable, you need to make sure that all accesses are made while holding a lock (any lock, provided it is the same for each access).
Making 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.
(source: the Java tutorials)

Two Synchronized blocks execution in Java

Why is it that two synchronized blocks can't be executed simultaneously by two different threads in Java.
EDIT
public class JavaApplication4 {
public static void main(String[] args) {
new JavaApplication4();
}
public JavaApplication4() {
Thread t1 = new Thread() {
#Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-1")) {
test(Thread.currentThread().getName());
} else {
test1(Thread.currentThread().getName());
}
}
};
Thread t2 = new Thread(t1);
t2.start();
t1.start();
}
public synchronized void test(String msg) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
System.out.println(msg);
}
}
public synchronized void test1(String msg) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
System.out.println(msg + " from test1");
}
}
}
Your statement is false. Any number of synchronized blocks can execute in parallel as long as they don't contend for the same lock.
But if your question is about blocks contending for the same lock, then it is wrong to ask "why is it so" because that is the purpose of the whole concept. Programmers need a mutual exclusion mechanism and they get it from Java through synchronized.
Finally, you may be asking "Why would we ever need to mutually exclude code segments from executing in parallel". The answer to that would be that there are many data structures that only make sense when they are organized in a certain way and when a thread updates the structure, it necessarily does it part by part, so the structure is in a "broken" state while it's doing the update. If another thread were to come along at that point and try to read the structure, or even worse, update it on its own, the whole thing would fall apart.
EDIT
I saw your example and your comments and now it's obvious what is troubling you: the semantics of the synchronized modifier of a method. That means that the method will contend for a lock on this's monitor. All synchronized methods of the same object will contend for the same lock.
That is the whole concept of synchronization, if you are taking a lock on an object (or a class), none of the other threads can access any synchronized blocks.
Example
Class A{
public void method1()
{
synchronized(this)//Block 1 taking lock on Object
{
//do something
}
}
public void method2()
{
synchronized(this)//Block 2 taking lock on Object
{
//do something
}
}
}
If one thread of an Object enters any of the synchronized blocks, all others threads of the same object will have to wait for that thread to come out of the synchronized block to enter any of the synchronized blocks. If there are N number of such blocks, only one thread of the Object can access only one block at a time. Please note my emphasis on Threads of same Object. The concept will not apply if we are dealing with threads from different objects.
Let me also add that if you are taking a lock on class, the above concept will get expanded to any object of the class. So if instead of saying synchronized(this), I would have used synchronized(A.class), code will instruct JVM, that irrespective of the Object that thread belongs to, make it wait for other thread to finish the synchronized block execution.
Edit: Please understand that when you are taking a lock (by using synchronized keyword), you are not just taking lock on one block. You are taking lock on the object. That means you are telling JVM "hey, this thread is doing some critical work which might change the state of the object (or class), so don't let any other thread do any other critical work" . Critical work, here refers to all the code in synchronized blocks which take lock on that particular Object (or class), and not only in one synchronized block.
This is not absolutely true. If you are dealing with locks on different objects then multiple threads can execute those blocks.
synchronized(obj1){
//your code here
}
synchronized(obj2){
//your code here
}
In above case one thread can execute first and second can execute second block , the point is here threads are working with different locks.
Your statement is correct if threads are dealing with same lock.Every object is associated with only one lock in java if one thread has acquired the lock and executing then other thread has to wait until first thread release that lock.Lock can be acquired by synchronized block or method.
Two Threads can execute synchronized blocks simultaneously till the point they are not locking the same object.
In case the blocks are synchronized on different object... they can execute simultaneously.
synchronized(object1){
...
}
synchronized(object2){
...
}
EDIT:
Please reason the output for http://pastebin.com/tcJT009i
In your example when you are invoking synchronized methods the lock is acquired over the same object. Try creating two objects and see.

Categories