Android NDK JNI C++ <15> pthread mutex互斥
多线程的互斥和信号,主要是用来保护临界区,即当有多个全局变量被多个线程可能同时访问时,其中一个或者多个线程可能修改这个全局变量或者对象,导致另外一个正在访问这个全局变量或者对象的线程出现数据突然变更,从而导致异常或者运算错误,为了避免这些情况,互斥和信号就被引入,但全局变量或者对象被调用时,将会被枷锁保护起来,防止线程在调用过程中出现全局变量或者对象突然变更的情况,该线程用完了,就解锁,另外的线程就可以接着使用了,大概是这么个道理.
步骤如下:
<1> : 新建一个Android工程,新建一个org的包,新建一个mutexClass.java.
<2> : 新建jni文件夹,onload.cpp,onload.h就不在这里show了,mutexclass.cpp如下:
#include <android/log.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include "onload.h" #define TAG "jni_thread" #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)) namespace android { pthread_mutex_t mutex1; typedef struct { int age; double scores; } ZONEDATA; ZONEDATA criticaldata; int cnd=0; void native_init() { } void* func_mutex(void* arg) { int i; i = *(int *) arg; // LOGI("value i : %d", i); LOGI("value cnd : %d", cnd); pthread_mutex_lock(&mutex1); //operation global variables //change global variables value or attribution criticaldata.age = criticaldata.age + (cnd++); pthread_mutex_unlock(&mutex1); LOGI("cnt : %d age : %d >", (cnd-1), criticaldata.age); pthread_detach (pthread_self()); pthread_exit((void *)0); } void* interupt_mutex(void* arg){ int i; for(i=0;i<100;i++){ cnd+=10; for(int j=0;j<100000;j++){ ; } } } void mutex_thread() { pthread_attr_t attr; pthread_t pthread_id[5]; pthread_t inter_t; int i; void* status; criticaldata.age = 100; criticaldata.scores = 12.0; pthread_mutex_init(&mutex1, NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_create(&inter_t, NULL, &interupt_mutex, (void*) NULL); for (i = 0; i < 5; i++) { pthread_create(&pthread_id[i], &attr, &func_mutex, (void*) &i); LOGI("cnts : %d ages : %d >", i, criticaldata.age); // sleep(1); } pthread_attr_destroy(&attr); for (i = 0; i < 5; i++) { pthread_join(pthread_id[i], &status); } pthread_mutex_destroy(&mutex1); pthread_exit (NULL); } } using namespace android; JNINativeMethod gMethods[] = { { "nativeinit", "()V", (void*) native_init }, { "mutexThread", "()V", (void*) mutex_thread } }; int register_android_mutex_jni_demo(JNIEnv *env) { return jniRegisterNativeMethods(env, "org/mutexClass", gMethods, sizeof(gMethods) / sizeof(gMethods[0])); }
最好删除pthread_exit (NULL);这一句.
<3> : 建立互斥的基本流程:
创建全局互斥对象->在主线程初始化互斥对象->创建要被保护的子线程->在子线程中调用全局变量之前,给互斥加上锁lock->使用完全局变量后,记得释放刚才那把锁unlock->调用exit,释放整个子线程.
<4> : 上面程序interupt_mutex是个干扰线程.
native thread exited without detaching这个异常的处理方式: http://blog.sina.com.cn/s/blog_8f9e665401013c9y.html
信号的处理和mutex差不多,建立信号的基本流程都是一样的,具体参见更详细的说明documents : http://www.360doc.com/content/09/1130/00/79031_10038898.shtml