I was doing some practice assignments and dabbling around with some dummy code for trying to develop a better understanding of the concepts of threads and locks. Following is a piece of code that (sometimes) goes into deadlock.
A.java
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
public synchronized void foo(boolean callBar) {
System.out.println("foo");
if (callBar) {
b.bar(false);
}
}
}
B.java
public class B {
private A a;
public void setA(A a) {
this.a = a;
}
public synchronized void bar(boolean callFoo) {
System.out.println("bar");
if (callFoo) {
a.foo(false);
}
}
}
Demo.java
public class Demo {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
new Thread(() -> {
a.foo(true);
}).start();
new Thread(() -> {
b.bar(true);
}).start();
}
}
Solution: I used Locks instead of synchronized.
A.java
public class A {
private final ReentrantLock lock = new ReentrantLock();
private B b;
public void setB(B b) {
this.b = b;
}
public ReentrantLock lock() {
return lock;
}
public boolean impendingExecute() {
Boolean thisLock = false;
Boolean otherLock = false;
try {
thisLock = lock.tryLock();
otherLock = b.lock().tryLock();
} finally {
if (!(thisLock && otherLock)) {
if (thisLock) {
lock.unlock();
}
if (otherLock) {
b.lock().unlock();
}
}
}
return thisLock && otherLock;
}
public void foo(boolean callBar) {
System.out.println("foo");
if (callBar && impendingExecute()) {
try {
b.bar(false);
} finally {
lock.unlock();
b.lock().unlock();
}
}
}
}
B.java
public class B {
private final ReentrantLock lock = new ReentrantLock();
private A a;
public void setA(A a) {
this.a = a;
}
public ReentrantLock lock() {
return lock;
}
public boolean impendingExecute() {
Boolean thisLock = false;
Boolean otherLock = false;
try {
thisLock = lock.tryLock();
otherLock = a.lock().tryLock();
} finally {
if (!(thisLock && otherLock)) {
if (thisLock) {
lock.unlock();
}
if (otherLock) {
a.lock().unlock();
}
}
}
return thisLock && otherLock;
}
public void bar(boolean callFoo) {
System.out.println("bar");
if (callFoo && impendingExecute()) {
try {
a.foo(false);
} finally {
lock.unlock();
a.lock().unlock();
}
}
}
}
After making the above changes, the code doesn't lead to a deadlock. Is it the proper way to implement this (Basically, I want the impendingExecute() method to be reviewed.)? Also, (deviating a bit from the review) are there any real world scenarios I can encounter this?
Note: I had posted this question on Code Review but it seems reviewal of dummy code is off-topic.
You can use java.util.concurrent.locks.ReentrantLock. This design permits the the method to attempt to acquire the locks of both the classes, to release the locks if it fails, and to try again later if necessary. If you are required to attempt until successful, then you need to put a it in a loop and terminate with some policy.
while (true) {
if (this.lock.tryLock()) {
try {
if (ba.lock.tryLock()) {
try {
//some logic
break;
} finally {
ba.lock.unlock();
}
}
} finally {
this.lock.unlock();
}
}
int n = number.nextInt(1000);
int TIME = 1000 + n; // 1 second + random delay to prevent livelock
Thread.sleep(TIME);
}
or you can use this solution which ensures that multiple locks are acquired and released in the same order:
if (compareTo(ba) < 0) {
former = this;
latter = ba;
} else {
former = ba;
latter = this;
}
synchronized (former) {
synchronized (latter) {
//Some logic
}
}
}
Related
Hi I have implemented my code like below two snippets but still I am not able to achieve synchronization in threads, as my methods are synchronized still no thread is waiting for other till complete. can you please let me know what mistake did I make in below snippet?
but when I put sleep on Thread in between then it works fine but that is not better way to implement by putting sleep on Thread
Option 1:
public class A{
public static void main(String args[]){
C c = new C();
ExecutorService executorService = Executors.newFixedThreadPool(10);
B t1 = new B(c);
for(int i = 1; i <=10; i++) {
executorService.submit(/*new B(c)*/t1);
}
executorService.shutdown();
try{
executorService.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS);
}catch(InterruptedException e){
System.out.println("Error while checking tread life: "+e);
}
}
}
public class B extends Thread{
C c;
static final Object lockObject = new Object();
public B(C c) {
this.c = c;
}
public void run(){
someProcess();
}
synchronized public void someProcess(){
String something = c.C();
if(something == null || "".equalsIgnoreCase(something)){
c.A();
}else{
c.B();
}
}
}
public class C {
synchronized public void method A(){
//insert the recods
}
synchronized public void method B(){
//update the records
}
synchronized public String method C(){
// searching a record to get it's id if it exist
return something;
}
}
Option 2:
public class A {
public static void main(String args[]) {
C c = new C();
ExecutorService executorService = Executors.newFixedThreadPool(10);
B t1 = new B(c);
for(int i = 1; i <=10; i++) {
executorService.submit(/*new B(c)*/t1);
}
if(executorService !=null) {
executorService.shutdown();
try {
executorService.awaitTermination (Long.MAX_VALUE,TimeUnit.NANOSECONDS);
}catch(InterruptedException e) {
System.out.println("Error while checking tread life: "+e);
}
}
}
}
public class B extends Thread {
C c;
static final Object lockObject = new Object();
public B(C c) {
this.c = c;
}
public void run() {
someProcess();
}
public void someProcess() {
synchronized(this) {
String something = c.C();
if(something == null || "".equalsIgnoreCase(something)) {
c.A();
}else{
c.B();
}
}
}
}
public class C {
synchronized public void method A() {
//insert the recods
}
synchronized public void method B() {
//update the records
}
synchronized public String method C() {
// searching a record to get it's id if it exist
return something;
}
}
Option 3:
public class A {
public static void main(String args[]) {
C c = new C();
ExecutorService executorService = Executors.newFixedThreadPool(10);
B t1 = new B(c);
for(int i = 1; i <=10; i++) {
executorService.submit(/*new B(c)*/t1);
}
if(executorService !=null) {
executorService.shutdown();
try {
executorService.awaitTermination (Long.MAX_VALUE,TimeUnit.NANOSECONDS);
}catch(InterruptedException e) {
System.out.println("Error while checking tread life: "+e);
}
}
}
}
public class B extends Thread {
C c;
static final Object lockObject = new Object();
public B(C c) {
this.c = c;
}
public void run() {
someProcess();
}
public void someProcess() {
synchronized(this) {
String something = c.C();
if(something == null || "".equalsIgnoreCase(something)) {
c.A();
}else{
c.B();
}
}
}
}
public class C {
public void method A() {
synchronized(this) {
//insert the recods
}
}
public void method B() {
synchronized(this) {
//update the records
}
}
public String method C() {
synchronized(this) {
// searching a record to get it's id if it exist
return something;
}
}
}
Option 4:
public class A {
public static void main(String args[]) {
C c = new C();
ExecutorService executorService = Executors.newFixedThreadPool(10);
B t1 = new B(c);
for(int i = 1; i <=10; i++) {
executorService.submit(/*new B(c)*/t1);
}
if(executorService !=null) {
executorService.shutdown();
try {
executorService.awaitTermination (Long.MAX_VALUE,TimeUnit.NANOSECONDS);
}catch(InterruptedException e) {
System.out.println("Error while checking tread life: "+e);
}
}
}
}
public class B extends Thread {
C c;
static final Object lockObject = new Object();
public B(C c) {
this.c = c;
}
public void run() {
someProcess();
}
public void someProcess() {
synchronized(lockObject) {
String something = c.C(lockObject);
if(something == null || "".equalsIgnoreCase(something)) {
c.A(lockObject);
}else{
c.B(lockObject);
}
}
}
}
public class C {
public void method A(Object lockObject) {
synchronized(lockObject) {
//insert the recods
}
}
public void method B(Object lockObject) {
synchronized(lockObject) {
//update the records
}
}
public String method C(Object lockObject) {
synchronized(lockObject) {
// searching a record to get it's id if it exist
return something;
}
}
}
Imagine a Java class with three methods:
master()
foo()
bar()
I want to synchronize master() and foo() and also master() and bar(), without synchronizing foo() and bar(). It can be done will a separate lock for every pair of synchronized methods, but my actual code has many more than three methods so I was hoping there's a way to do it without so many lock objects.
You are essentially describing a ReadWriteLock. Every two methods are allowed to run simultaneously (a "read lock"), except for master(), which excludes all others (a "write lock"):
public class MyClass {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock r = rwLock.readLock();
private final Lock w = rwLock.writeLock();
public void master() {
w.lock();
// do stuff
w.unlock();
}
public void foo() {
r.lock();
// do stuff
r.unlock();
}
public void bar() {
r.lock();
// do stuff
r.unlock();
}
}
You can use synchronized on any Object. So, you can create a separate lock for the methods:
public class Lock {
private final Object master_foo = null;
private final Object master_bar = null;
public void master() {
synchronized(master_foo) {
synchronized(master_bar) {
...
}
}
}
public void foo() {
synchronized(master_foo) {
...
}
}
public void bar() {
synchronized(master_bar) {
...
}
}
}
I would go with Mureinik's answer, but just for the heck of it, here's another way you can set up read/write synchronization (untested):
public class Test {
private final Semaphore semaphore = new Semaphore(Integer.MAX_VALUE);
public void master() {
semaphore.acquireUninterruptibly(Integer.MAX_VALUE);
try {
//...
} finally {
semaphore.release(Integer.MAX_VALUE);
}
}
public void foo() {
semaphore.acquireUninterruptibly();
try {
//...
} finally {
semaphore.release();
}
}
public void bar() {
semaphore.acquireUninterruptibly();
try {
//...
} finally {
semaphore.release();
}
}
}
I have two methods in two different classes, like this
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
System.out.println("This is A and B ");
}
}
#Override
public void run() {
methodAandB();
}
}
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
System.out.println("This is A or B");
}
}
#Override
public void run() {
methodAorB(a);
}
}
Thread t1 is calling methodAandB().
Thread t2 is calling methodAorB().
Can I switch between these two threads after each iteration of loop in methods?
I want to get output like this:
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
Best example of flip-flop between threads:
Given two int array (even and odd), 2 threads printing their numbers in natural order.
package com.rough;
public class ThreadsBehaviour {
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
int a[] = {1,3,5,7,9};
int b[] = {2,4,6,8,10};
Thread odd = new Thread(new Looper(a, lock));
Thread even = new Thread(new Looper(b, lock));
odd.start();
even.start();
}
}
class Looper implements Runnable
{
int a[];
Object lock;
public Looper(int a[], Object lock)
{
this.a = a;
this.lock = lock;
}
#Override
public void run() {
for(int i = 0; i < a.length; i++)
{
synchronized(lock)
{
System.out.print(a[i]);
try
{
lock.notify();
if(i == (a.length - 1))
{
break;
}
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can achieve this simply by using the shared variables. I have implemented and verified the problem. code is below
class X
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassXdone)
{}
System.out.println("This is A and B ");
GlobalClass.isClassXdone = true;
GlobalClass.isClassYdone = false;
}}
#Override
public void run() {
methodAandB(); } }
ClassY
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassYdone)
{}
System.out.println("This is A or B ");
GlobalClass.isClassYdone = true;
GlobalClass.isClassXdone = false;}}
#Override
public void run() {
methodAorB();}}
Definition of the shared variable
public class GlobalClass {
public static boolean isClassXdone = false ;
public static boolean isClassYdone = false ;
}
You can just start your thread using t1.start and t2.start to get the desired output
Thread t1 = new Thread(new ClassX());
Thread t2 = new Thread(new ClassY());
t1.start();
t2.start();
This is probably more than needed to solve the problem, but, as it seems to be an introduction to concurrent programming exercise, it should be along the lines of what you'll encounter.
You should probably have a shared object that both your threads know, so that they may synchronize through it. Like so:
public class MyMutex {
private int whoGoes;
private int howMany;
public MyMutex(int first, int max) {
whoGoes = first;
howMany = max;
}
public synchronized int getWhoGoes() { return whoGoes; }
public synchronized void switchTurns() {
whoGoes = (whoGoes + 1) % howMany;
notifyAll();
}
public synchronized void waitForMyTurn(int id) throws
InterruptedException {
while (whoGoes != id) { wait(); }
}
}
Now, your classes should receive their respective identifier, and this shared object.
public class ClassX implements Runnable {
private final int MY_ID;
private final MyMutex MUTEX;
public ClassX(int id, MyMutex mutex) {
MY_ID = id;
MUTEX = mutex;
}
public void methodAandB() {
for(int i = 0; i < 10; i++) {
try {
MUTEX.waitForMyTurn(MY_ID);
System.out.println("This is A and B ");
MUTEX.switchTurns();
} catch (InterruptedException ex) {
// Handle it...
}
}
}
#Override
public void run() { methodAandB(); }
}
ClassY should do the same. Wait for its turn, do its action, and then yield the turn to the other.
I know it's a little late to answer this. But it's yesterday only I have come across this question. So I guess it's never too late.. ;)
Solution, as #afsantos mentioned is having a shared object between the two threads and implementing mutual exclusion on the shared object. The shared object could be alternatively locked by the two threads. Two possible implementations are as follows. This is actually more like an extension of #afsantos solution. His work is hereby acknowledged.
Solution 1:
Blueprint of the object that will be shared is as follows.
public class MutEx {
public int whoGoes, howMany;
public MutEx(int whoGoes, int howMany) {
this.whoGoes = whoGoes;
this.howMany = howMany;
}
public synchronized void switchTurns(){
this.whoGoes = (this.whoGoes + 1) % 2;
notifyAll();
}
public synchronized void waitForTurn(int id) throws InterruptedException{
while(this.whoGoes != id)
wait();
}
}
Then, you could implement the ClassX as follows.
public class ClassX implements Runnable {
private final int MY_ID;
private final MutEx MUT_EX;
public ThreadOne(int MY_ID, MutEx MUT_EX) {
this.MY_ID = MY_ID;
this.MUT_EX = MUT_EX;
}
#Override
public void run(){
this.doTheWork();
}
public void doTheWork(){
for(int i = 0; i < 10; i++){
try {
MUT_EX.waitForMyTurn(MY_ID);
System.out.println("This is A and B");
MUT_EX.switchTurns();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ClassY also will be the same, with whatever the differences you need to be there. Then, in the invocation (i.e. in the main method),
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
Thread t1 = new Thread(new ClassX(0, mutEx);
Thread t2 = new Thread(new ClassY(1, mutEx));
t1.start();
t2.start();
}
Voila! You have two threads, alternating between each as you need.
Solution 2: Alternatively, you could implement the ClassX & ClassY as follows.
public class ClassX extends Thread{
Here, you are subclassing the java.lang.Thread to implement your requirement. For this to be invoked, change the main method as follows.
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
ClassX t1 = new ClassX(0, mutEx);
ClassY t2 = new ClassY(1, mutEx);
t1.start();
t2.start();
}
Run this, and you have the same result.
If you don't need to use Thread try this code:
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
methodAandB();
} else {
methodAorB();
}
}
I have a method getNewA() that is supposed to block until some other thread calls setA(x). Is it correct to use a CountDownLatch? I noticed that there is a data race in that there is a possibility that after gate.await() unblocks another thread will call setA(x) using the old latch, therefore it might be possible to miss a value. I thought about synchronizing getNewA() but wouldn't that result in a deadlock? Any suggestions on how to approach this?
package test;
import java.util.concurrent.CountDownLatch;
public class A {
private int a;
private CountDownLatch gate;
public A(int a) {
a = 1;
gate = new CountDownLatch(1);
}
A getNewA() throws InterruptedException { // wait for new a...
gate.await();
gate = new CountDownLatch(1);
return this;
}
public synchronized int getA() {
return a;
}
public synchronized void setA(int a) {
gate.countDown();
this.a = a;
}
}
Use a Phaser. You can reuse it just like you want here without having to create a new instance of the your barrier.
public class A {
private int a
private final Phaser phaser = new Phaser(1);
public A(int a) {
a = 1;
}
A getNewA() throws InterruptedException { // wait for new a...
phaser.awaitAdvance(phaser.getPhase());
return this;
}
public synchronized int getA() {
return percent;
}
public synchronized void setA(int a) {
this.a = a
phaser.arrive();
}
}
Each time setA is called it will increment to a new phase and the phaser.awaitAdvance(phaser.getPhase()) will return out. At this point the new phase will equal the phaser.getPhase()+1
Note: this requires Java 7.
An alternative is to handle synchronization yourself. What I think you want is for the getA to return a value that is set after a thread currently enters. You can use this as the wait() criteria.
public class A {
private int a;
private long updateCount = 0;
private final Object lock = new Object();
public A getNewA() throws InterruptedException { // wait for new a...
synchronized(lock) {
long currentCount = updateCount ;
while (currentCount == updateCont) {//assumes never decrementing
lock.wait();
}
return this;
}
}
public int getA() {
synchronized(lock) {
return a;
}
}
public void setA(int a) {
synchronized(lock) {
this.a = a;
updateCount++;
lock.notifyAll();
}
}
}
Edit: Race condition is possible as TomAnderson mentioned. Thanks
You could use a Semahore:
package test;
import java.util.concurrent.Semaphore;
public class A {
private int a
private Semaphore semaphore = new Semaphore(0);
public A(int a) {
a = 1;
}
A getNewA() throws InterruptedException { // wait for new a...
semaphore.acquire();
return this;
}
public synchronized int getA() {
return percent;
}
public synchronized void setA(int a) {
this.a = a;
semaphore.release();
}
}
If the semaphore has 0 permits left and two threads call getA one after the other, both will block and only of them will be non-deterministically chosen to wake up when setA is called.
If setA is called twice in a sequence, it will allow two threads to call getA next time, which may not be what you want, since both of them will get the same reference to this.
I want to have such kind of work flow using explicit lock/condition variables (It's a course project which mandates this style.): A is the main class, it asks B to do some job from time to time. B has a worker class C which constantly queries B about new jobs to do and do it. After C finishes, it will call A's callback function to notify A the job is done.
However when I try to run the program, I get an IllegalMonitorStateException, when the callback() is trying to notify the doit() function.
exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Test$A.callback(Test.java:49)
at Test$C.run(Test.java:115)
I looked at the javadoc and some Q&A about this exception, but still no idea why I get this.
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class Test {
public class A
{
private ReentrantLock lock;
private Condition cond;
private boolean bool;
private B b;
public A()
{
this.lock = new ReentrantLock();
this.cond = lock.newCondition();
b = new B(this);
bool = false;
}
public void doit()
{
try {
lock.lock();
b.letgo();
while (!bool) {
System.out.println("A::doit() Block.");
cond.awaitUninterruptibly();
}
System.out.println("A::doit() Done.");
}
finally {
lock.unlock();
}
}
public void callback() {
try {
lock.lock();
bool = true;
cond.notify();
System.out.println("A::callback() done.");
}
finally {
lock.unlock();
}
}
}
public class B
{
private C c;
private ReentrantLock lock;
private Condition cond;
private boolean bool;
public B(A a)
{
this.lock = new ReentrantLock();
this.cond = lock.newCondition();
bool = false;
c = new C(a, this);
c.start();
}
public void letgo()
{
try {
lock.lock();
bool = true;
}
finally {
lock.unlock();
}
}
public void get()
{
try {
lock.lock();
while (!bool) {
cond.awaitUninterruptibly();
}
bool = false;
return;
}
finally {
lock.unlock();
}
}
}
public class C extends Thread
{
private A a;
private B b;
public C(A a, B b)
{
this.a = a;
this.b = b;
}
public void run()
{
while (true) {
b.get();
a.callback();
}
}
}
public static void main(String args[])
{
Test t = new Test();
t.test1();
}
public void test1()
{
A a = new A();
a.doit();
}
}
Use the signal() method on Condition in place of notify().
While you can successfully synchronize on a Condition instance, and then use the traditional wait() and notify() methods, you might as well just use an Object if you aren't using the extended capabilities of the concurrent classes.
Condition was intended to be used with the equivalent methods await() and signal(), and their enhanced variants.