This is the third part of the Concurrency series. For your convenience you can find other parts in the table of contents in Part 1 – Mutex performance in .NET

Last time we saw file lock in Java which we can use on every platform. However, if we stick to Windows only, we can use WinAPI mutexes through JNI. Let’s go.

Code

First, Java application:

public class JavaMutex {
    static {
        System.out.println(System.getProperty("java.library.path"));
        System.loadLibrary("MutexJava");
    }

    private native long createMutex();
    private native void acquireMutex(long mutex);
    private native void releaseMutex(long mutex);

    private void test(){
        long mutex = createMutex();

        while(true){
            long startTime = System.currentTimeMillis();
            for(int i=0;i<100000;++i){
                acquireMutex(mutex);
                releaseMutex(mutex);
            }
            long estimatedTime = System.currentTimeMillis() - startTime;
            System.out.println(estimatedTime);
        }
    }

    public static void main(String[] args){
        new JavaMutex().test();
    }
}

We define three methods to use Mutex. Observe that we use long instead of HANDLE. HANDLE is a void* which we can consider a number in our case.

Next, we generate the JNI header:

javac -h . JavaMutex .java

and here is the result:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class JavaMutex */

#ifndef _Included_JavaMutex
#define _Included_JavaMutex
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JavaMutex
 * Method:    createMutex
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_JavaMutex_createMutex
  (JNIEnv *, jobject);

/*
 * Class:     JavaMutex
 * Method:    acquireMutex
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_JavaMutex_acquireMutex
  (JNIEnv *, jobject, jlong);

/*
 * Class:     JavaMutex
 * Method:    releaseMutex
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_JavaMutex_releaseMutex
  (JNIEnv *, jobject, jlong);

#ifdef __cplusplus
}
#endif
#endif

Now we implement the methods in C++ with Visual Studio 2017:

#include 

JNIEXPORT jlong JNICALL Java_JavaMutex_createMutex
(JNIEnv *, jobject) {
	HANDLE mutex = CreateMutex(NULL, FALSE, L"mutex_java");
	return (jlong)mutex;
}

JNIEXPORT void JNICALL Java_JavaMutex_acquireMutex
(JNIEnv *, jobject, jlong mutex) {
	WaitForSingleObject((HANDLE)mutex, INFINITE);
}

JNIEXPORT void JNICALL Java_JavaMutex_releaseMutex
(JNIEnv *, jobject, jlong mutex) {
	ReleaseMutex((HANDLE)mutex);
}

Compile, run with -Djava.library.path="..." and test.

Results

    \[ \begin{array}{cc} Number\ of\ processes & Time [ms] \\ 1 & 80\\ 2 & 575\\ 3 & 892\\ 4 & 1244\\ 5 & 1502\\ 6 & 1886\\ 7 & 2239\\ 8 & 2593\\ 9 & 2865\\ 10 & 3175\\ \end{array} \]

As we can see, the results are quite nice, even better than .NET. Next time we will see if we can improve C# code.