Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutually exclusive method execution in Java

I have two methods: a() and b(). While I'm fine with multiple threads accessing any of the methods at the same time (that is desirable), I do not want any threads to enter a() while b() is being executed. How do I do that?

Edit 1

Lets say there are 4 threads and Thread 1 is accessing A(). What I want is all of the 4 threads should not use B().

like image 374
milan Avatar asked Nov 10 '12 09:11

milan


People also ask

What is mutually exclusive in Java?

Mutual Exclusive helps keep threads from interfering with one another while sharing data. It can be achieved by using the following three ways: By Using Synchronized Method. By Using Synchronized Block.

What displays mutually exclusive items for selection in Java?

MutuallyExclusiveFrame subclass of Frame. It simply creates a new MutuallyExclusiveMenu and shows the text indicating which option in the menu is currently selected. The MutuallyExclusiveMenu class is an alternative to a Panel with a bunch of mutually exclusive radio buttons.

Are mutually exclusive?

Mutually exclusive is a statistical term describing two or more events that cannot happen simultaneously. It is commonly used to describe a situation where the occurrence of one outcome supersedes the other. For example, war and peace cannot coexist at the same time. This makes them mutually exclusive.

Which will contain the body of the thread?

10. Which will contain the body of the thread? run();


2 Answers

CHECK UPDATE at the bottom - I don't think this approach can work. Leaving it for information.


You could use a Semaphore:

  • if a thread is in b(), a thread trying to execute a() will block until the execution of b() is over.
  • if a thread is in b() and a second thread tries to run b() it will be able to
  • if 2 threads execute a() while b() is not being executed both will run

Note: once a thread is in a() and has passed the "semaphore test", another thread can start running b() before the end of a()

The principle should work but I have not tested it.

private final Semaphore inB = new Semaphore(1);

public void a() throws InterruptedException {
    inB.acquire(); //blocks until no thread is in b any longer
    //now we are good to go and execute a()
    //release the semaphore immediately for other threads who want to run a()
    inB.release(); 
    //rest of your code here
}
public void b() {
    //does not block to allow 2 thread running b() simultaneously
    boolean needToRelease = inB.tryAcquire(); 
    //rest of your code
    //if the permit was acquired, release it to allow threads to run a()
    if (needToRelease) {
        inB.release();
    }
}

EDIT

Your intention is not clear and your question has been edited because one of your comments says that you want a() and b() to be mutually exclusive (many threads can run either a() or b() in parallel, but a() and b() should never be run in parallel). In that case, you can use the same logic with 2 semaphores inA and inB.


UPDATE => BUG

As pointed out by @yshavit in a comment to another answer, there is a race condition in the code in the following scenario:

  • T1 runs a() and acquires inB
  • T2 runs b() and fails to acquire inB
  • T1 releases inB
  • T3 runs a() and manages to acquire inB although T2 is running b()

It seems that this can't be achieved with Sempahores only. This answer gives a better solution.

like image 156
assylias Avatar answered Oct 07 '22 19:10

assylias


Exception handling ommitted for simplicity:

public class Test {
  private final Object lock = new Object();
  private int counterA;
  private int counterB;

  public void a() {
    synchronized(lock) {
      while(counterB > 0) {
        lock.wait();
      }
      ++counterA;
    }

    // do work

    synchronized(lock) {
      --counterA;
      lock.notifyAll();
    }
  }

  public void b() {
    synchronized(lock) {
      while(counterA > 0) {
        lock.wait();
      }
      ++counterB;
    }

    // do work

    synchronized(lock) {
      --counterB;
      lock.notifyAll();
    }
  }
}
like image 24
Marc-Christian Schulze Avatar answered Oct 07 '22 18:10

Marc-Christian Schulze