java synchronized on object vs synchronized on this - java

i want to write own simple semaphore and done it as follows:
class Semaphore {
private boolean done;
private final Object lock = new Object();
public Semaphore(boolean done){ this.done = done;}
public void acquire() throws InterruptedException {
synchronized (lock) {
while (!done)
lock.wait();
done = false;
}
}
public void release() {
synchronized (lock) {
done = true;
lock.notify();
}
}
}
it works fine. But if i replace synchronized (lock) with synchronize (this) it begins to throw IllegalMonitorStateException. Why so?

As #Alexei Kaigorodov mentioned in comment, when you replace synchronized (lock) with synchronize (this). Then, you need to also replace lock to this in your code.
As this indicate to current object which is different than lock object.
Now, you replaced synchronized (lock) with synchronize (this) which means now you are trying to acquire lock on current object but you were waiting on object of Object class.
This works absolutely fine :
public void acquire() throws InterruptedException {
synchronized (this) {
while (!done)
this.wait();
done = false;
}
}
public void release() {
synchronized (this) {
done = true;
this.notify();
}
}

Related

lock and unlock in multi thread java

I use lock and unlock in the my code And start some Customer and Producer Thread.
line lock.waite throws IllegalMonitorStateException.Why?
With the lock, the conditions for using this list are not provided in one Thread?
static class Customeer extends Thread {
private List<String> list;
private Lock lock;
public Customeer(List<String> list, Lock lock) {
this.list = list;
this.lock = lock;
}
#Override
public void run() {
lock.lock();
if (list.size() == 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.remove(0);
lock.unlock();
}
}
static class Producer extends Thread {
private List<String> list;
private Lock lock;
public Producer(List<String> list, Lock lock) {
this.list = list;
this.lock = lock;
}
#Override
public void run() {
lock.lock();
list.add("hello");
list.notify();
lock.unlock();
}
}
You have some problems with your code, namely:
list.wait(); you can't acquire the list's monitor unless you are within a synchronized method (or block code).
list.notify();, you can't release the list's a monitor unless you are within a synchronized method (r block code).
You can't use .wait() or .notify() from none synchronized method or section.
Change your code like that snippet:
static class Customeer extends Thread {
private List<String> list;
private Lock lock;
public Customeer(List<String> list, Lock lock) {
this.list = list;
this.lock = lock;
}
#Override
public void run() {
lock.lock();
if (list.size() != 0) {
list.remove(0);
}
lock.unlock();
}
}
static class Producer extends Thread {
private List<String> list;
private Lock lock;
public Producer(List<String> list, Lock lock) {
this.list = list;
this.lock = lock;
}
#Override
public void run() {
lock.lock();
list.add("hello");
lock.unlock();
}
}
These strings are calling IllegalMonitorStateException.
line lock.wait throws IllegalMonitorStateException. Why?
Actually, there is no such line.
However, there is a line that calls list.wait(). And that is the cause of your problems.
In order to call wait() on an object, you must first be holding the primitive mutex lock on that object. You can only get that kind of lock using synchronized. (Either a synchronized method or a synchronized block.)
In your case:
You are calling wait on the List instance.
You are locking the Lock instance.
You are holding the wrong kind of lock for Object.wait. You are holding a Lock lock, not holding a primitive mutex lock.
So ... if you want to do the equivalent of wait and notify on a Lock instance, then when you need to do is to call Lock.newCondition() to get a Condition object. Then you use it like this:
private final Lock lock = ...
private final Condition cond = lock.newCondition();
try {
lock.acquire();
while (!the_condition_we_are_waiting_for) {
cond.await();
}
// do stuff
} finally {
lock.release();
}
For reference, the above would look like this if you rewrote it to use a primitive mutex.
private final Object lock = new Object();
synchronized(lock) {
while (!the_condition_we_are_waiting_for) {
lock.wait();
}
// do stuff
}
(You could use any object as the lock, but it is a good idea to use an object that is hidden, and won't be locked by any other code.)
In summary, either use a primitive mutex with synchronized, Object.wait and Object.notify* OR use a Lock with Lock.acquire, Lock.release, Condition.await and Condition.signal. Don't try to mix the two kinds of locking and condition variables.

How to handle two thread pause in a method

The situation is like this, methodB() is called again and again when the app is running. When methodC() is called, methodB() will pause until methodC() is done. When methodA() is called, it will pause until methodB() done for three times but skip "Code X".
I've tried to add locker2, lock2 and threadLocker2() to do the pause of methodA(), but it didn't work as methodB() also pause. Can anyone give me some suggestions how can I do this?
private final Object locker = new Object();
private boolean lock = false;
public void methodA() {
//Lock until methodB() run three times
//Do something
}
public void methodB() { //A thread called again and again
//Do something
threadLock();
//Code X
}
public void methodC() {
lock true;
//Do something
lock = false;
synchronized (locker) { locker.notify(); }
}
private void threadLock() {
synchronized (locker) {
while (lock) {
try {
locker.wait();
} catch (InterruptedException e) {}
}
}
}
I would use an atomic boolean (or integer) or a volatile boolean for that.
This is the shared atomic / volatile boolean:
private AtomicBoolean secondMethodIsDone = new AtomicBoolean(false);
void firstMethod() {
methodInOtherThread();
while(!secondMethodIsDone.get()) {
//thread sleep waiting...
}
// do your things when second is done
}
This happens in another thread:
void methodInOtherThread() {
// do your stuff
// whenever is done:
secondMethodIsDone.set(true);
}
This should do it.

how to resolve deadlock causes by the synchronized method

I encountered the issue like the Deadlocks and Synchronized methods. In this case, methodA, methodB, A.last() all must be the synchronized method. So I am going to resolve this issue by removing synchronized in the method B.last(). Any deadlock in this solution? Could you please let me know any solution to resolve this better?
Class A
{
synchronized void methodA(B b)
{
b.last();
}
synchronized void last()
{
System.out.println(“ Inside A.last()”);
}
}
Class B
{
synchronized void methodB(A a)
{
a.last();
}
synchronized void last()
{
System.out.println(“ Inside B.last()”);
}
}
Class Deadlock implements Runnable
{
A a = new A();
B b = new B();
// Constructor
Deadlock()
{
Thread t = new Thread(this);
t.start();
a.methodA(b);
}
public void run()
{
b.methodB(a);
}
public static void main(String args[] )
{
new Deadlock();
}
}
In general, to avoid deadlocks, either use only one lock at all, or make sure that locks are always acquired in the same order.
Assuming that you decide A always has to be locked before B, a minimally invasive bugfix for your example (assuming that nothing else synchronizes against A or B objects) would be this in class B:
void methodB(A a) {
synchronized(a) {
synchronized(this) {
// do whatever was in methodB before, including...
a.last();
}
}
}
That way, if both locks are required, lock of A is always acquired first, causing no deadlocks.
You can also do the same with the Java 5+ java.util.concurrent locks. Removing a synchronized where not needed is of course also an option to solve the deadlock (but if synchronization was needed, it will cause race conditions instead which are usually worse than a deadlock).
You can use a common mutex such as a ReentrantLock or synchronized blocks between the two methods instead of synchronized.
ReentrantLock example:
Class A
{
A(Lock lock) {
this.lock = lock;
}
private Lock lock;
void methodA(B b)
{
lock.lock();
try {
b.last();
} finally {
lock.unlock();
}
}
void last()
{
lock.lock();
try {
System.out.println(“ Inside A.last()”);
} finally {
lock.unlock();
}
}
}
Class B
{
B(Lock lock) {
this.lock = lock;
}
private Lock lock;
void methodB(A a)
{
lock.lock();
try {
a.last();
} finally {
lock.unlock();
}
}
void last()
{
lock.lock();
try {
System.out.println(“ Inside B.last()”);
} finally {
lock.unlock();
}
}
}
Class Deadlock implements Runnable
{
Lock lock = new ReentrantLock();
A a = new A(lock);
B b = new B(lock);
// Constructor
Deadlock()
{
Thread t = new Thread(this);
t.start();
a.methodA(b);
}
public void run()
{
b.methodB(a);
}
public static void main(String args[] )
{
new Deadlock();
}
}
synchronized block example:
Class A
{
A(Object lock) {
this.lock = lock;
}
private Object lock;
void methodA(B b)
{
synchronized(lock){
b.last();
}
}
void last()
{
synchronized(lock){
System.out.println(“ Inside A.last()”);
}
}
}
Class B
{
B(Object lock) {
this.lock = lock;
}
private Object lock;
void methodB(A a)
{
synchronized(lock){
a.last();
}
}
void last()
{
synchronized(lock){
System.out.println(“ Inside B.last()”);
}
}
}
Class Deadlock implements Runnable
{
Object lock = new Object();
A a = new A(lock);
B b = new B(lock);
// Constructor
Deadlock()
{
Thread t = new Thread(this);
t.start();
a.methodA(b);
}
public void run()
{
b.methodB(a);
}
public static void main(String args[] )
{
new Deadlock();
}
}

synchronize 2 method with another method but not with each other

I have methodA and methodB and methodSync in my java program.
I want that when a thread is inside methodSync other threads don't run the methodA and methodB and wait for methodSync to end. But methodA and methodB can run simultaneously.
If I want to sync 3 methods with each other I can use this code:
private static final Object LOCK = new Object();
public static void methodA() {
synchronized (LOCK) {
//Do Job
}
}
public static void methodB() {
synchronized (LOCK) {
//Do Job
}
}
public static void methodSync() {
synchronized (LOCK) {
//Do Job
}
}
But this is not a solution for me because I want to run methodA and methodB simultaneously.
private static final Object A = new Object();
private static final Object B = new Object();
public static void methodA() {
synchronized (A) {
//Do Job
}
}
public static void methodB() {
synchronized (B) {
//Do Job
}
}
public static void methodSync() {
synchronized (A) {
synchronized (B) {
//Do Job
}
}
}
I guess that will work. Good luck.
P.S. You can replace synchronized with ReadWriteLock (acquiring the read lock in methods A & B and the write lock in methodSync. If that's worth doing is if you want two callers in methodA at the same time.

Does synchronized(this) imply that the current thread object acquired its own lock?

Consider the following piece of code -
class MyThread extends Thread {
private int x = 5;
public void run() {
synchronized (this) // <-- what does it mean?
{
for (int i = 0; i < x; i++) {
System.out.println(i);
}
notify();
}
}
}
class Test {
public static void main(String[] args) {
MyThread m = new MyThread();
m.start();
synchronized (m) {
try {
m.wait();
} catch (InterruptedException e) {
}
}
}
}
In the above example, does Thread m acquire the lock on itself?
The current thread acquires the lock on the associated instance of the MyThread class.
The synchronized(this) is locking the same object as synchronized(m) in main().
Finally,
public void run() {
synchronized (this) {
is exactly equivalent to
public synchronized void run() {
Yes, that's exactly what it means. The thread acquires a lock on the instance of the class (MyThread).
You have to see it as any other java object. what you have typed means that other threads can't access this java object (independently if it was a thread instance or not because it doesn't make difference.

Categories

Resources