线程同步之互斥锁
int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);
int pthread_mutex_lock(pthread_mutex_t* mutex);
int pthread_mutex_unlock(pthread_mutex_t* mutex);
int pthread_mutex_destroy(pthread_mutex_t* mutex);
#include <jni.h>
#include <string>
#include <cstdio>
#include <pthread.h>
#include <unistd.h>
struct NativeWorkerArgs {
jint id;
jint iteration;
};
static jmethodID gOnNativeMessage = nullptr;
static JavaVM *gVm = nullptr;
static jobject gObj = nullptr;
static pthread_mutex_t mutex;
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
gVm = vm;
return JNI_VERSION_1_6;
}
static void *nativeWorkerThread(void *args) {
JNIEnv *env = nullptr;
if (0 != pthread_mutex_lock(&mutex)) {
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to lock mutex");
goto exit;
}
if (0 == gVm->AttachCurrentThread(&env, nullptr)) {
NativeWorkerArgs *nativeWorkerArgs = (NativeWorkerArgs *) args;
for (int i = 0; i < nativeWorkerArgs->iteration; ++i) {
char message[26];
sprintf(message, "Worker %d: Iteration %d", nativeWorkerArgs->id, i);
jstring messageString = env->NewStringUTF(message);
env->CallVoidMethod(gObj, gOnNativeMessage, messageString);
if (nullptr != env->ExceptionOccurred())
break;
sleep(1);
}
delete nativeWorkerArgs;
gVm->DetachCurrentThread();
}
if (0 != pthread_mutex_unlock(&mutex))
{
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to unlock mutex");
}
exit:
return (void *) 1;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zhuhongxi_nativcethreaddemo1_MainActivity_nativeInit(JNIEnv *env, jobject thiz) {
if (0 != pthread_mutex_init(&mutex, nullptr)) {
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to initialize mutex");
goto exit;
}
if (nullptr == gOnNativeMessage) {
jclass clazz = env->GetObjectClass(thiz);
gOnNativeMessage = env->GetMethodID(clazz, "onNativeMessage", "(Ljava/lang/String;)V");
if (nullptr == gOnNativeMessage) {
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to find method");
}
}
if (nullptr == gObj) {
gObj = env->NewGlobalRef(thiz);
if (nullptr == gObj) {
goto exit;
}
}
exit:
return;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zhuhongxi_nativcethreaddemo1_MainActivity_nativeFree(JNIEnv *env, jobject thiz) {
if (nullptr != gObj) {
env->DeleteGlobalRef(gObj);
gObj = nullptr;
if (0 != pthread_mutex_destroy(&mutex)) {
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to destroy mutex");
}
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zhuhongxi_nativcethreaddemo1_MainActivity_posixThreads(JNIEnv *env, jobject thiz,
jint threads, jint iterations) {
pthread_t *handles = new pthread_t[threads];
for (jint i = 0; i < threads; i++) {
NativeWorkerArgs *nativeWorkerArgs = new NativeWorkerArgs();
nativeWorkerArgs->id = i;
nativeWorkerArgs->iteration = iterations;
pthread_t thread;
int result = pthread_create(&handles[i], nullptr, nativeWorkerThread,
(void *) nativeWorkerArgs);
if (0 != result) {
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to create native thread");
goto exit;
}
}
exit:
return;
}