Behavior of synchronized method and block is different - java

I observed a scenario where use of synchronized method or synchronized block producing different results.
From below code:
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("]");
}
}
class Caller implements Runnable{
String msg;
Callme target;
Thread t;
public Caller(Callme target, String msg) {
this.target = target;
this.msg = msg;
t = new Thread(this, "Caller thread");
t.start();
}
#Override
public void run() {
synchronized(target) {
target.call(msg);
new Callme().call(msg);
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
Callme obj = new Callme();
new Caller(obj, "thread1");
new Caller(obj, "thread2");
new Caller(obj, "thread3");
Thread.currentThread().join();
}
}
When I use the synchronized block in the Caller::run method the ouput is synchronized as below:
[thread1]
[thread1]
[thread3]
[thread3]
[thread2]
[thread2]
But when I use the synchronized method for the Callme::call method, instead of synchronized block, the output is not synchronized:
[thread1]
[thread1[thread2]
]
[thread3[thread2]
]
[thread3]
My Expectation is the output should not be synchronized on both cases because I am using different objects when calling the "Callme::call" method
This made me question my understanding of the Synchronized block concept?

A synchronized method is equivalent to a synchronized(this)-block for the length of the entire method, however your code is using synchronized(target), and target is a shared instance of Callme. In other words: the object being synchronized on is different, so the behavior is not the same.
In the case you use synchronized(target), it means that all threads synchronize on the same instance of Callme so their behavior is serial: a thread will hold the monitor of that Callme instance for the whole duration of the Caller.run method, so in effect the threads are executed one after the other.
In the case of a synchronized method, the threads each synchronize on their own instance of Caller, so in effect there is no serialization (except for the writes to System.out).
Some additional remarks:
Calling Thread.currentThread().join() is a bad idea, because it will wait on itself
In general don't create and start Thread instances in the Runnable implementation that is going to be run by that thread: you lose access to the thread. Especially don't do this in the constructor, because you are publishing a partially constructed object to the Thread, which is not a big problem in this code, but might lead to subtle bugs in more complex applications.

Related

Method synchronized , but code produces random result due to non-serialized thread behaviour

Here is my code:
public class ThreadDemo {
public static void main(String args[]) throws Exception {
Printer[] printers = new Printer[5];
printers[0] = new Printer("#base");
printers[1] = new Printer("#try");
printers[2] = new Printer("!test");
printers[3] = new Printer("^hello");
printers[4] = new Printer("*world");
for (Printer x : printers) {
x.start();
}
try {
for (Printer y : printers) {
y.join();
}
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
class Printer extends Thread {
public Printer(String name) {
super(name);
}
public void run() {
print();
}
public synchronized void print() {
for (int i = 0; i < 10; i++) {
System.out.print(getName().charAt(0));
try {
sleep(100);
} catch (InterruptedException e) {
System.out.println(e + " occured");
}
}
}
}
It results in
#^!#**#^!#*##!^#*#^!#^!*#^*#!##!#*^##^!*!#^#*##*^!
My expectation is that all symbols would be serialized as #####^^^^^ based on which thread starts first.
Calling sleep() would let other threads to proceed until sleeptime of current thread , but i guess that should not be the case with synchronized method.
The synchronised doesn't come into play here.
That keyword makes sure that you can't invoke the same method on the same object in parallel.
You are invoking it on different objects, therefore the result would be the same even without the keyword in place!
( I rather assume that the result you see is in fact caused by using println() here. That is a "really slow" operation that introduces "de facto" synchronisation when used by threads that are super-quick doing all their other work. I am trying to find some additional information about that, but that might take some more time )
The issue with your code or I would say your expectation is that the method print is synchronized at the object level and you are creating new thread objects, starting the thread and calling this method.
So in this case, each method is synchronized on each individual thread object. To achieve the behavior you expect, we can make the print method static and see the behavior change. You will get the expected result because then, the method print is synchronized on a single instance of Printer class lock. So even if different threads instance are calling this method, because there is a single lock for class, thread execution happens sequentially.
public static synchronized void print() {
for (int i = 0; i < 10; i++) {
System.out.print(Thread.currentThread().getName().charAt(0));
try {
sleep(100);
} catch (InterruptedException e) {
System.out.println(e + " occured");
}
}
}
#SolomonSlow - So it has to be corrected as 'No Synchronized methods' can be called on the same object at same time ?
There is only one thing you will ever need to know about a synchronized instance method. You need to know that this...
synchronized void Foobar() { ... }
...Is just a shortcut way of writing a synchronized block.
void Foobar() {
synchronized (this) {
...
}
}
Both of those method declarations do exactly the same thing. So, everything you know or learn about how synchronized blocks behave can be applied to synchronized methods too.
The most important thing to know about synchronized blocks is, "No two threads can ever be synchronized on the same object at the same time." If you understand that, and if you know how a synchronized method is just a shortcut for a synchronized block, then you can answer your own question.

Why Java throw java.lang.IllegalMonitorStateException when I invoke wait() in static way synchronized block?

I do not understand why Java throw exception from subject in this code. Could somebody explain me it?
class Wait implements Runnable
{
public void run() {
synchronized (Object.class) {
try {
while(true) {
System.out.println("Before wait()");
wait();
System.out.println("After wait()");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ObjectMethodInConcurency
{
public static void main(String[] args) {
Wait w = new Wait();
(new Thread(w)).start();
}
}
Use synchronized (this) { instead of synchronized (Object.class) in your class
EDIT
Reasoning behind the IllegalMonitorException in above code
In Java using synchronized keyword is a way to create and obtain a monitor object which will be used as lock to execute corresponding code block.
In the above code that monitor is "Object.class".
And wait() method tells the current thread to wait until it is notifyed and you have to invoke wait() on the monitor object which owns the lock.
So the way to invoke wait() method is like below otherwise you will get IllegalMonitorException.
synchronized(monitor){
monitor.wait();
}
So for your example you can either use "Object.class.wait()" or change the monitor to this since you are calling wait() method on the current instance

synchronise on non-final object [duplicate]

This question already has answers here:
Synchronizing on an object in java, then changing the value of the synchronized-on variable
(4 answers)
Closed 5 years ago.
private volatile Object obj = new MyObject();
void foo()
{
synchronized(obj)
{
obj.doWork();
}
}
void bar()
{
synchronized(obj)
{
obj.doWork();
obj = new MyObject(); // <<<< notice this line (call it line-x)
}
}
Suppose at a certain point in time, a thread t_bar is executing bar(), and another one t_foo is executing foo, and that t_bar has just acquired obj, so t_foo is, in effect, waiting.
After the sync-block in bar is executed, foo will get to execute its sync-block, right? What value of obj would it see? The old one? Or the new one set in bar?
(I would hope that the new value is seen, that's the whole point of coding it that way, but I want to know if this is a 'safe' bet)
In the exact situation you described, yes, the read of obj inside foo's synchronized block will see the new value set by the previous bar's synchronized block.
The fun part is, it doesn't always happen in that exact situation. The program is not thread safe, for example, if immediately after bar() exits, the same threads invokes another bar(), while the foo thread is locking on the old object. The bar thread locks on the new object, so the two threads are executing concurrently, both executing obj.doWork() on the same new obj.
We can probably partially fix it by
// suppose this line happens-before foo()/bar() calls
MyObject obj = new MyObject();
void foo()
while(true)
MyObject tmp1 = obj;
synchronized(tmp1)
MyObject tmp2 = obj;
if(tmp2==tmp1)
tmp2.doWork();
return;
// else retry
this at least guarantees no current invocations of obj.doWork() on the same obj, since obj.doWork() can only occur in a synchronized block that locks the exact same obj
It will behave normally as if object reference was not changed internally. Reason being that test for lock on object will be done only once. So even if object changes internally, thread will keep waiting and behaviour will remian same as if object was same [unchanged].
I tried another thing. I placed a sleep statement just after new object was created and then started the next thread and as expected both threads started working simultaneously.
See the code below.
public class ChangeLockObjectState {
private volatile Object obj = new Object();
void foo() {
synchronized (obj) {
try {
System.out.println("inside foo");
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void bar() {
synchronized (obj) {
try {
System.out.println("inside bar");
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
obj = new Object(); // <<<< notice this line (call it line-x)
System.out.println("going out of bar");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("wait over");
}
}
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final ChangeLockObjectState test = new ChangeLockObjectState();
new Thread(new Runnable() {
#Override
public void run() {
test.bar();
}
}).start();
Thread.sleep(6000);
new Thread(new Runnable() {
#Override
public void run() {
test.foo();
}
}).start();
}
}
The new value is shown. And it works even without the making obj volatile. That's because the sychronization is still hold on the old object and provides visibility to the new value once the waiting thread (t_foo) gets inside. Here is the test:
public class Main3 {
private MyObject obj = new MyObject(1);
void foo()
{
synchronized(obj)
{
System.out.println(obj.number);
obj.doWork();
}
}
void bar()
{
synchronized(obj)
{
System.out.println(obj.number);
obj.doWork();
//force the foo thread to wait at the synchronization point
for(int i = 0; i < 1000000000l; i++);
obj = new MyObject(2); // <<<< notice this line (call it line-x)
}
}
public static void main(String[] args) throws InterruptedException {
final Main3 m3 = new Main3();
Thread t1 = new Thread( new Runnable() {
#Override
public void run() {
m3.bar();
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
m3.foo();
}
});
t1.start();
t2.start();
}
}
class MyObject {
int number;
public MyObject(int number) {
this.number = number;
}
public void doWork() {
}
}
This is unsafe and broken. Changing the object you lock on doesn't work.
When a thread tries to enter a synchronized block it first has to evaluate the expression in parens in order to figure out what lock it needs. If the lock changes after that, the thread doesn't have any way of knowing that, it eventually acquires the old lock and enters the synchronized block. At that point it sees the object and evaluates that, getting the new reference, and calls the method on it with the old (now irrelevant) lock, and without holding the new lock, even though some other thread might have the new lock held and could be executing the method on the same object concurrently.
The new value of obj will be read.
From the standard's section on Happens before:
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
From definition of shared variable:
All instance fields, static fields, and array elements are stored in heap memory. In this chapter, we use the term variable to refer to both fields and array elements.
Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.
The read of obj inside of the synchronized block is separate from the initial evaluation of the expression obj to determine the which object's build-in monitor to lock. The reassignment of obj will happen before the first read, but not the second. Since obj is a volatile field, that second read must see the updated value of obj.

waiting Thread never wakes up

I have a ThreadManager with two Threads. One for gui-relevant requests and one for measurement-relevant requests. The are both running and checking their queue of requests, if there is any, they are processing the request. One can add requests at any time, using the static ThreadManager.addGuiRequest(eGuiRequest) and ThreadManager.addMeasRequest(eMeasRequest) methods. Now both of those need to be initialized which is done by adding a INIT request to the corresponding queue. But the initialization of the measurement is depending on the fact that the gui is already initialized. I tried to solve this using wait()/notify(), but I can not get it working.
Here is a SSCCE. At startup, both queues have a INIT request added and are then started. The measurement initialization detects that the gui is not yet initialized and perfomrs a wait(). The gui initializes (simulated by sleeping for 5s). This all works fine.
After the gui initialized, it tries to wake up the measurement thread, but the measurement thread does not wake up... I based my wait()/notify() code on this article. What is going wrong here?
import java.util.LinkedList;
import java.util.NoSuchElementException;
public class ThreadManager {
public static void main(String[] args) {
new ThreadManager();
ThreadManager.addMeasRequest(eMeasRequest.OTHER_STUFF);
}
public enum eGuiRequest { INIT, OTHER_STUFF; }
public enum eMeasRequest { INIT, OTHER_STUFF; }
private static LinkedList<eGuiRequest> guiQueue = new LinkedList<eGuiRequest>();
private static LinkedList<eMeasRequest> measQueue = new LinkedList<eMeasRequest>();
private static Thread guiThread, measThread;
protected boolean initialized = false;
public ThreadManager() {
final int waitMs = 200;
guiThread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
if (guiQueue.isEmpty()) sleepMs(waitMs);
else {
eGuiRequest req = guiQueue.getFirst();
processGuiRequest(req);
guiQueue.removeFirst();
}
} catch (NoSuchElementException e) {}
}
}
private void processGuiRequest(eGuiRequest req) {
System.out.println("T: " + "Processing Gui request: " + req);
switch (req) {
case INIT:
// do some initializiation here - replaced by a wait:
sleepMs(5000);
System.out.println("I: " + "guiThread finished, waking up measThread");
synchronized (measThread) {
initialized = true;
measThread.notify();
}
break;
case OTHER_STUFF:
// do other stuff
break;
}
}
});
measThread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
if (measQueue.isEmpty()) sleepMs(waitMs);
else {
eMeasRequest req = measQueue.getFirst();
processMeasurementRequest(req);
measQueue.removeFirst();
}
} catch (NoSuchElementException e) {}
}
}
private void processMeasurementRequest(eMeasRequest req) {
if (req == eMeasRequest.INIT) { // if init, wait until GUI is initialized
synchronized (this) {
while (!initialized) {
System.out.println("I: " + "measThread waits for guiThread to finish initializiation");
try {
wait();
} catch (Exception e) {}
System.out.println("I: " + "measThread awakes");
}
}
}
System.out.println("T: " + "Processing Measurement request: " + req);
// process request here:
sleepMs(5000);
}
});
addGuiRequest(eGuiRequest.INIT);
addMeasRequest(eMeasRequest.INIT);
guiThread.start();
measThread.start();
}
public static void sleepMs(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException ee) {}
}
public static void addGuiRequest(eGuiRequest req) {
guiQueue.add(req);
}
public static void addMeasRequest(eMeasRequest req) {
measQueue.add(req);
}
}
The GUI thread calls notify() on measThread (of type Thread), and the processMeasurementRequest() method calls wait() on this, which is the Runnable instance used by measThread.
I would advise using a specific object, shared by both threads to wait and notify:
private static final Object GUI_INITIALIZATION_MONITOR = new Object();
Also, instead of using a LinkedList and sleeping an aritrary time between requests, I would use a BlockingQueue: this would allow the consuming thread to handle a request as soon as there is one, and would avoid unnecessary wakeups from the sleeping state.
Also, instead of the low-level wait/notify, you could use a CountDownLatch initialized to 1. The GUI thread would countDown() the latch when it's initialized, and the mesurement thread would await() the latch until the GUI thread has called countDown(). This would delegate complex synchronization and notification stuff to a more high-level, well-tested object.
The main problem is that you call notify() on measThread, but wait() is called on an anonymous class. The easiest way to fix this is to create a special object for synchronization. For example, you create a field:
private static final Object LOCK = new Object();
Then you write synchronized blocks using this object and call its methods like this:
synchronized (LOCK) {
while (!initialized) LOCK.wait();
}
Also I have to say that this piece of code doesn't use any synchronization at all for the fields accessed from different threads, which means that it can break at any time. Both queues are accessed outside the threads created by you, this means that you should either access them with a lock held all the time, or you can make them thread safe by using a built-in synchronized list:
quiQueue = Collections.synchronizedList(new LinkedList<eGuiRequest>());
initialized is accessed from synchronized blocks, but right now they synchronize on different locks (I have described this problem at the start of my answer). If you fix this problem, initialized will also be working as it should.
Just do not sent init request to measurment at startup. Sent it from processGuiRequest() after execution of init gui request. Then no wait/notify stuff is needed.

Synchronize thread and a method with an object?

I have a method and a thread which I'd like to run in the following order: First the method should do something with an object, and then the thread should do something with the object. They share the same object. I have to synchronize them, but I am just meeting with Threads. How can I do that?
private synchronized method()
{
//do something with an object (a field)
}
Runnable ObjectUpdater = new Runnable()
{
//do something with the object after the method has finished
}
My code, that somehow manages to freeze my Main thread (where the method is)
My thread code:
private Runnable something = new Runnable(){
synchronized (this){
while (flag == false)
{ try {wait();)
catch (IntExc ie) {e.printStackTrace...}
}
//here it does its thing
}
setFlag(false);
}
My method code (part of the main thread)
private void Method()
{
//do its thing
setFlag(true);
notifyAll();
}
To me that is simple questions
" you said that I do not know which is
going to access the object first - the
separate ObjectUpdater thread, or the
main thread (with the method). If the
separate thread accesses it before the
main thread, that is bad and I don't
want this to happen"
if you want the main thread method to call first then the objectUpdater thread , have a flag to know whether the method is visited first by main thread ,if it is updater then call wait to this thread , once main finishes it call notify which will run separator thread,
to know which thread is main thread or updater thread , set a name to the thread while creating it. and get the name as Thread.currentThread().getName().
Use the Semaphore class to allow access to the object.
public class Main
{
public static void main (String[] args) {
final Obj obj = new Obj();
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
semaphore.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return;
}
obj.doSomething();
}
});
t.setName("test");
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
obj.doSomething();
semaphore.release();
}
}
class Obj {
public void doSomething() {
System.out.println("something done by " + Thread.currentThread());
}
}
Apart from synchronizing on the object, you could call the method as first statement in the new thread, or you could start the new thread at the end of the method.
It is hard to say what is the best approach in your case, maybe you can give us some more details on the how and what?
Update
In answer to your code (for some reason I cannot add another comment...)
Is the method called from a synchronized(this) block? If not the notifyAll() should be in a synchronized block. Also, can you update the code to show where/how your main thread interacts with the method and the object?
I think better approach would be to call the method using which you want to perform something with an object, and then declare the thread which would do something with an object.

Categories

Resources