with code such as
synchronized (this)
{
mTimeOutRunnable = new Runnable()
{
#Override
public void run()
{
..some code
}
};
}
the reference assignement of the new Runnable class is covered by the block but will code inside run() (which is asyncronously called outside of the block) enter into the synchronized block also?
I wrapped in the sync block in the first place as this is called from a worker thread and I want to ensure the calling (main) thread has access to the mTimeOutRunnable object also.
No, only the assignment of your Runnable to mTimeOutRunnable is covered by the synchronized block, not subsequent calls to the run() method.
mTimeOutRunnable = new Runnable()
{
#Override
public void run()
{
..some code
}
};
is same as
synchronized(this){
obj = new SomeClass();
}
So only the reference assignment is covered by synchronized block
Related
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.
I have next code:
boolean signal;
#Test
public void test() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (!signal){
// empty loop body
}
}
});
thread.start();
Thread.sleep(1000);
signal = true;
thread.join();
}
It runs infinity loop due to creation of local copy of signal variable in thread. I know that I can fix it by making my signal variable volatile. But also loop can successfully exit if add synchronized block inside my loop (even empty):
boolean signal;
#Test
public void test() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (!signal){
synchronized (this) {
}
}
}
});
thread.start();
Thread.sleep(1000);
signal = true;
thread.join();
}
How synchronized updates my signal value inside thread?
Synchronized does not updates the signal value itself, it basically just places a couple of flags to avoid two threads use the same object at the same time; something like: MonitorEnter and MonitorExit.
The first one locks the object, and the second one releases.
Take a look at the following article: how-the-java-virtual-machine-performs-thread-synchronization.
Please notice the article is very old; but as far as I understand the logic behind remains.
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello");
}
}
}).run();
System.out.println("Bye");
}
In the main thead, I create a new thread, which will print "hello" every second. Why the final "Bye" never got print? In the other word, why the child thread blocks the main thread?
Because you are calling run(), instead of start().
You must never call run() directly. If you call start(), the program will call run() for you, in a different thread. (Like you wanted.) By calling run() yourself, you are going into the run() method with the parent thread, and get stuck in an eternal loop, with your parent thread.
The following code blocks in synchronized sync() method before calling plain() method. Why is this so, shouldn’t the intrinsic lock block call to synchronized methods only – for example this behavior would have been fine if plain() was synchronized as well.
As the monitor concept that java uses is applicable to synchronized methods/blocks only – it by definition should not affect execution of non synchronized code. Is this always the case or is this behavior JVM implementation specific.
public class Main {
public static void main(final String[] args) {
final Main main = new Main();
new Thread(new Runnable() {
#Override
public void run() {
main.sync();
}
}).run();
main.plain();
}
public synchronized void sync() {
try {
System.out.println("sleeping...");
Thread.sleep(2000);
System.out.println("out...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void plain() {
System.out.println("plain...");
}
}
Output:
sleeping...
out...
plain...
You should call start() rather than run() on the new Thread. Calling run() will execute the runnable's run method in the current thread, rather than starting a new thread to run it.
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.