Thread calling non-synchronized instance method when a synchronized method is called - java

public class Common {
public synchronized void synchronizedMethod1() {
System.out.println("synchronizedMethod1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedMethod1 done");
}
public void method1() {
System.out.println("Method 1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 1 done");
}
}
public class MyThread extends Thread {
private int id = 0;
private Common common;
public MyThread(String name, int no, Common object) {
super(name);
common = object;
id = no;
}
public void run() {
System.out.println("Running Thread" + this.getName());
try {
if (id == 0) {
common.synchronizedMethod1();
} else {
common.method1();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Common c = new Common();
MyThread t1 = new MyThread("MyThread-1", 0, c);
MyThread t2 = new MyThread("MyThread-2", 1, c);
t1.start();
t2.start();
}
}
Output:
Running ThreadMyThread-1
synchronizedMethod1 called
Running ThreadMyThread-2
Method 1 called
synchronizedMethod1 done
Method 1 done
I would like to find a way to prevent method1() from running when i called synchronizedMethod1. Unless I'm mistaken all methods are called and Java compiles them during and before runtime regardless if it's synchronized or not.
Should i have used a Lock object instead and/or not also make method1() a synchronized method?

I would like to find a way to prevent method1() from running when i called synchronizedMethod1
The easiest way to do this is to make method1() also be synchronized. This will mean that both methods will cause a lock on the instance of Common that they are calling. Only one thread will be able to either be calling synchronizedMethod1() or method1().
Unless I'm mistaken all methods are called and Java compiles them during and before runtime regardless if it's synchronized or not.
I don't understand this question. You really should not have to worry about the compilation or optimization phase of the JVM.
Should i have used a Lock object instead?
Usually making a method synchronized is considered not as good as using a private final lock object. Lock objects just allow you to be more fine grained in your locks. For example, with method locking, log messages and other statements that do not need protection will be synchronized as well. But if the goal is to lock the entire method then synchronizing the methods is fine.

If you want method1 and synchronizedMethod1 to be mutually exclusive then you need to guard them with the same lock. Whether this is using a Lock or simply calling synchronize on the same Object instance, the outcome is roughly the same.
On the off chance you want multiple threads to be allowed to execute method1 but not when synchronizedMethod1 is being invoked, you need a ReadWriteLock to accomplish that.
public class Common {
ReadWriteLock rwLock = new ReentrantReadWriteLock();
public void synchronizedMethod1() {
rwLock.writeLock().lock();
try {
System.out.println("synchronizedMethod1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronizedMethod1 done");
} finally {
rwLock.writeLock().unlock();
}
}
public void method1() {
rwLock.readLock().lock();
try {
System.out.println("Method 1 called");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 1 done");
} finally {
rwLock.readLock().unlock();
}
}
}

Related

Possibility of deadlock with two locks?

Can this code deadlock with thread 1 calling one and thread 2 calling two. That is, can the acquisition of the inner lock be reordered to before the acquisition of the outer one (from the POV of the other thread)?
private final Object foo = new Object();
synchronized void one() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
synchronized void two() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
No, this will not deadlock.
When synchronized methods are called the intrinsic lock of this is locked before the method’s body is executed. Here either thread 1 or thread 2 will get to run its method, and the other one will not be able to lock on the intrinsic lock of this.foo so the owner of the lock of this will be able to lock this.foo.
So for with a Simple Test :
class LockTest implements Runnable {
public final Object foo = new Object();
boolean runOne;
public LockTest(boolean runOne) {
this.runOne = runOne;
}
synchronized void one() {
System.out.println("runnin one function");
synchronized(this.foo) {
try {
System.out.println("Enter Sleep function one");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void two() {
System.out.println("running two function");
synchronized(this.foo) {
try {
System.out.println("enter sleep function two");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void run() {
if(runOne)
one();
else
two();
}
}
With this in a Main class :
while (true)
{
LockTest document2 = new LockTest(true);
LockTest document3 = new LockTest(false);
Thread tread1 = new Thread(document2);
Thread tread2 = new Thread(document3);
tread1.start();
tread2.start();
a++;
if(a==10)
break;
}
We are not locking and even watching with a Thread Dump everything is working Fine. Why? Because every time we are initializating a new Thread with a new object foo. But if that object is declared as static it will be a lock and the others threads need to wait. So from my test and POV. No, it can't be deadlocked.

What can cause IllegalMonitorStateException in the given sample code

I am trying to learn java concurrency programming. Kindly check my sample code and help me understanding why I'm getting "java.lang.IllegalMonitorStateException" even though I have called wait() and notify in a synchronized context.
public class Test {
public static void main(String[] args) throws Exception {
Test t1 = new Test();
t1.m1();
}
private void m1() {
Example ex = new Example();
Thread t1 = new Thread(ex);
t1.start();
synchronized (ex) {
System.out.println("waiting");
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Example implements Runnable {
#Override
public void run() {
System.out.println("Running");
notifyMethod();
}
private void notifyMethod() {
System.out.println("Notifying");
synchronized (this) {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
notify();
}
}
}
}
I expect out of "waiting,running,notifying" but the actual output is:
waiting
Running
java.lang.IllegalMonitorStateException
Notifying
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at examples.Test.m1(Test.java:18)
at examples.Test.main(Test.java:8)
First of, I think synchonizing on a Runnable isn't a good idea (Example in your case). You either synchonize on this or, even better, on a dedicated Object, that is lock in my example. Edit: Synchronizing on a Runnable is the same as using this but for me it looks better. Guts tell me there might be something more to that, but I'm not an expert in this field. Dedicated lock Object is always better, read this article if you want to find out more on the topic.
Then, while synchonizing on a lock, you have to call wait() on that same object: lock.wait(). If you synchronize on this, then you call this.wait() or just wait().
When you want to notify the waiting thread, you again have to synchronize on the lock and call notify() on that object: lock.notify(). Both the monitor in the synchronize and the object on which you call notify() have to be the exact same object you have called wait() on.
Here is a code that works:
public class Test {
public static final Object lock = new Object();
public static void main(String[] args) throws Exception {
Test t1 = new Test();
t1.m1();
}
private void m1() {
Example ex = new Example();
Thread t1 = new Thread(ex);
t1.start();
synchronized (lock) {
System.out.println("waiting");
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class Example implements Runnable {
#Override
public void run() {
System.out.println("Running");
notifyMethod();
}
private void notifyMethod() {
System.out.println("Notifying");
synchronized (lock) {
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
lock.notify();
}
}
}
}

Is it fine to call this synchronized method from a synchronized block?

Simply put, I'm wondering if this changes the behavior. I'm assuming yes, because calling someMethod() will lock the entire object, instead of just the list object? But I'm still new to this synchronization stuff, so I'd like some more educated feedback.
The before:
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The After:
public void run() {
int i = 0;
while (!end) {
synchronized (list) {
while (list.size() == i) {
someMethod();
}
}
}
}
public synchronized void someMethod() {
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You are correct - the new code has got different semantics, as someMethod() is indeed synchronized on the instance it is being invoked on (and as such, that synchronization is entirely unrelated to the one on list). However, the call to someMethod() will take place while the monitor on list is being held, so a call to run() is "equally thread safe" with respect to list.
On the other hand, you have now introduced the possibility for multiple threads to call someMethod() directly at the same time. You have also introduced a (probably unnecessary) potential for deadlock with other threads due to the extra synchronization on the object itself. I would recommend this instead:
public void someMethod() {
synchronized (list) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This method is now safe both for individual use and for being called through run() - note that it is safe to synchronize on an object that you have already synchronized on; the thread won't block itself.
With syncronized you don't really 'lock' an object. You will just make sure that access from everyone who is synchronizing on that specific object is 'regulated' with a lock.
A synchronized method is synchronizing on this.
That means, if you enter a syncronized block on some object list you can call a syncronized method without a problem at first
Some things to be thought about:
This code doesn't produce a deadlock:
public void foo() {
synchronized (this) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
because you already have the "lock" on this, but this:
public void foo() {
synchronized (list) {
someMethod();
}
}
public synchronized void someMethod() {
// ...
}
may produce a deadlock with some other thread! You'll have to be really careful if you enter a synchronized section within another synchronized section

Why the "show" word also gets printed by the second thread although we have applied the synchronized keyword meaning we have locked the object

Here is my code
class Thread1 extends Thread
{
public synchronized void show()
{
System.out.println("show");
System.out.println(Thread.currentThread().getName());
try
{
Thread.sleep(5000);
}
catch(Exception e)
{
System.out.println(e);
}
}
public synchronized void display()
{
System.out.println("Display");
System.out.println(Thread.currentThread().getName());
}
public static void main(String args[])
{
Thread1 z=new Thread1();
z.set();
}
public void set()
{
Thread1 tr=new Thread1();
Thread1 tr1=new Thread1();
tr.start();
tr1.start();
}
public void run()
{
try
{
show();
display();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
I assume you meant to ask about why show is printed by both threads before either of the thread names are printed.
You are synchronizing your instance methods, so they are implicitly locking on the object on which the method is called. However, you have 2 different Thread1 objects locking on themselves, so neither thread is stopping the other from entering the synchronized methods.
If you intend to have only one Thread execute each of the synchronized methods at a time, then you need to lock on a common object. Use a synchronized block that locks on Thread1.class.
Here is what that looks like for the show method.
public void show()
{
synchronized (Thread1.class)
{
System.out.println("show");
System.out.println(Thread.currentThread().getName());
try
{
Thread.sleep(5000);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
The display method can be modified similarly.
You are instantiating two different objects that have their own state (tr and tr1). They never access the same synchronised block, and thus never block waiting for the other one to finish.
Try moving the show method to another class, instantiate that class and then pass it to tr and tr1 as a constructor parameter, for example.

Java wait specific interval notify not working

Code snippet:
class Counter implements Runnable {
Object s = new Object();
#Override
public void run() {
try {
synchronized (s) {
s.wait(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
//...do Something
}
public void stopCounter() {
synchronized (s) {
s.notifyAll();
}
}
}
Irrespective of whether i call stopCounter or not, the ...do Something code always executes only after the wait interval. Even after notify it still waits for 10 secs.
I cannot tell from your example what you are trying to achieve. If it is to try and replace some sort of polling then consider the BlockingQueue interface that was released in Java 5. Since that has appeared I have had no need for wait/notify. It's a lot more simple to use and java behind the scenes does the equivalent of the wait/notify for you.
It depends of the way you use it. I have just tried it by adding a main method and running it and it seems like the wait / notify mechanism is working fine, not the way you described it. Please try it yourself:
public static void main(String[] args) {
Counter c = new Counter();
new Thread(c).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
c.stopCounter();
}
My guess is that you call the run and stopCounter methods on different instances of your Counter class. They therefore use different monitors (your s = new Object()) and the call to stop won't notify the other Counter.
For example, this would behave similarly to what you describe (unless you get a spurious wakeup):
public static void main(String[] args) throws InterruptedException {
Counter c = new Counter();
new Thread(c).start();
Thread.sleep(200);
new Counter().stopCounter();
}
static class Counter implements Runnable {
Object s = new Object();
#Override
public void run() {
try {
System.out.println("in");
synchronized (s) {
s.wait(10000);
}
System.out.println("out");
} catch (InterruptedException e) {
e.printStackTrace();
}
//...do Something
}
public void stopCounter() {
synchronized (s) {
s.notifyAll();
}
System.out.println("notified");
}
}

Categories