5

I'm learning about Mutex and Semaphore in Java. So I thought of getting my hands dirty.

I understand that mutex is semaphore with single permit from this link and mutex has the concept of ownership from this link.

To demonstrate ownership I wrote below program and found below output. When I do release more than acquires, it actually increases the number of permits.

Below is the program.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;

public class MutexOwnerShipDemo {
    public static void main(String[] args) {
        Semaphore mutex = new Semaphore(1);
        final ExecutorService es = Executors.newSingleThreadExecutor();
        try {
            // acquire mutex lock permit in main thread
            mutex.acquire();

            // release the lock in different thread
            Future mutexWait = es.submit(() -> mutex.release());
            mutexWait.get();
            System.out.println("mutexWait.isDone() " + mutexWait.isDone() );
            System.out.println("successfully released permits for mutex \n " +
                "available permits are " + mutex.availablePermits());

            // release the lock in main thread
            mutex.release();
            System.out.println( "available permits are " + mutex.availablePermits());

            // release lock in main thread once again
            mutex.release();
            System.out.println( "available permits are " + mutex.availablePermits());
        } catch (Exception e) {

        }
        Runtime.getRuntime().addShutdownHook(new Thread(() -> es.shutdownNow()));
        System.out.println(es.isShutdown());
    }
}

The output is -

mutexWait.isDone() true
successfully released permits for mutex 
available permits are 1
available permits are 2
available permits are 3
false

Is this behavior expected. If so, how this works

My java installation details -

$ java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
user51
  • 8,843
  • 21
  • 79
  • 158

2 Answers2

7

Yes, it's the expected behaviour cited in the documentation:

[...] Releases a permit, increasing the number of available permits by one. [...] There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire().

You can release as many permits as you want to:

Semaphore semaphore = new Semaphore(0);
semaphore.release(10); // it's fine
System.out.println(semaphore.availablePermits()); // 10

You can't obtain a random number of permits (precisely, a number that exceeds the current number of permits available), though:

Semaphore semaphore = new Semaphore(0);
semaphore.acquire(10); // you are blocked here

Semaphore semaphore = new Semaphore(0);
System.out.println(semaphore.tryAcquire(10)); // false
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
3

A couple of things:

  • you're using a Semaphore, which can have any number of permits, so yes it is expected. See the Javadoc:

There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.

  • you're not using multiple threads since you're always blocking in futures. Your code is fully sequential.
  • when people say a mutex is a semaphore with a single permit, they're talking about the abstract concepts, not the Java implementations. Example of mutexes in Java would be a ReentrantLock, or a simple Object used with a synchronized block.
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Dici
  • 25,226
  • 7
  • 41
  • 82