Android NDK執行緒篇(四)
Android NDK執行緒篇
前言
本篇重點介紹原生執行緒的相關知識,包括執行緒基礎知識,執行緒同步等,學完本篇,你將會對NDK原生執行緒有一個更加深入的認識。
執行緒基礎
執行緒是程序併發執行多工的機制,執行緒可以共享程序的各種資源,程序內的多個執行緒之間可以相互通訊,也可以通過一定的方式進行執行緒,比如互斥鎖,訊號量等。
原生執行緒
我們可以通過Java執行緒來執行原生程式碼,也可以通過原生執行緒來執行。
Java執行緒
Java執行緒基礎
我們可以通過Thread類來建立Java執行緒,也可以通過執行緒池來建立Java執行緒。
Java執行緒同步
本小節重點介紹原生程式碼使用Java物件進行執行緒同步。
原生程式碼可以通過MonitorEnter和MonitorExit函式來使用Java物件進行執行緒同步。
示例如下:
extern
"C"
JNIEXPORT
void
JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_jniLock(JNIEnv*
env, jobject
thiz,jobject
obj) {
env->MonitorEnter(obj);
//do something
env->MonitorExit(obj);
}
POSIX執行緒
POSIX執行緒基礎
Android NDK的執行緒是通過POSIX標準實現的,所以也叫POSIX
執行緒標頭檔案
#include <pthread.h>
POSIX執行緒函式
執行緒建立函式
int pthread_create(pthread_t *thread, pthread_attr_t const * attr, void *(*start_routine)(void *), void * arg);
函式解釋:
thread引數代表pthread_t型別的執行緒指標
attr引數代表執行緒的屬性指標
start_routine引數代表執行緒的執行函式的指標
arg引數代表要傳入執行緒可執行函式的引數
執行緒等待函式
intpthread_join(pthread_t thid, void ** ret_val);
函式解決:
thid引數代表pthread_t執行緒
ret_val代表執行緒可執行函式返回值的指標
執行緒退出函式
void pthread_exit(void * retval);
函式解釋:
retval代表執行緒要返回的值
示例程式碼
void * threadFunc(void *arg){ int count=*(int*)arg; for(int i=0;i<count;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i); } return (void *) 0; } extern "C" JNIEXPORT void JNICALL Java_com_kgdwbb_jnistudy_MainActivity_startNativeThread(JNIEnv* env, jobject thiz,jint count) { pthread_t pthread; int *arg=new int(count); pthread_create(&pthread,NULL,threadFunc,arg); int *retvalue=0; pthread_join(pthread,(void**)*retvalue); if(*retvalue!=0){ __android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred"); } }
POSIX執行緒同步
POSIX執行緒目前支援兩種執行緒同步方式,分別是互斥體和訊號量,下面分別介紹這兩種執行緒同步方式。
互斥體Mutex
標頭檔案
#include <pthread.h>
函式宣告
Mutex初始化函式
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
函式解釋:
mutext引數代表要建立的互斥體指標
attr引數代表要建立的互斥體的屬性,可以為NULL
Mutex鎖定函式
int pthread_mutex_lock(pthread_mutex_t *mutex);
函式解釋:
mutext引數代表通過pthread_mutex_init函式建立的互斥體指標
Mutex解鎖函式
int pthread_mutex_unlock(pthread_mutex_t *mutex);
函式解釋:
mutext引數代表通過pthread_mutex_init函式建立的互斥體指標
Mutext銷燬函式
int pthread_mutex_destroy(pthread_mutex_t *mutex);
函式解釋:
mutext引數代表通過pthread_mutex_init函式建立的互斥體指標
示例程式碼
void * threadFunc(void *arg){ pthread_mutex_t* pthread_mutex=(pthread_mutex_t*)arg; pthread_mutex_lock(pthread_mutex); for(int i=0;i<10;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i); } pthread_mutex_unlock(pthread_mutex); return (void *) 0; } extern "C" JNIEXPORT void JNICALL Java_com_kgdwbb_jnistudy_MainActivity_startNativeThread(JNIEnv* env, jobject thiz,jint count) { pthread_mutex_t pthread_mutex; if(pthread_mutex_init(&pthread_mutex,NULL)!=0) return; pthread_t pthreads[count]; for(int i=0;i<count;i++){ pthread_create(&pthreads[i],NULL,threadFunc,&pthread_mutex); } for(int i=0;i<count;i++){ int retvalue=0; pthread_join(pthreads[i],(void**)&retvalue); if(retvalue!=0){ __android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred"); } } pthread_mutex_destroy(&pthread_mutex); }
訊號量Semaphore
標頭檔案
#include <semaphore.h>
函式宣告
Semaphore初始化函式
extern int sem_init(sem_t *sem, int pshared, unsigned int value);
函式解釋:
sem引數代表要建立的Semaphore指標
pshared引數代表要建立的Semaphore的數量
value代表要建立的Semaphore的初始數量
Semaphore獲取函式
extern intsem_wait(sem_t *sem);
函式解釋:
sem引數代表已建立的Semaphore指標
Semaphore釋放函式
extern intsem_post(sem_t *sem);
函式解釋:
sem引數代表已建立的Semaphore指標
Semaphore銷燬函式
extern intsem_destroy(sem_t *sem);
函式解釋:
sem引數代表已建立的Semaphore指標
示例程式碼
void * threadFunc(void *arg){ sem_t* sem=(sem_t*)arg; sem_wait(sem); for(int i=0;i<5;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i); } sem_post(sem); return (void *) 0; } extern "C" JNIEXPORT void JNICALL Java_com_kgdwbb_jnistudy_MainActivity_startNativeThread(JNIEnv* env, jobject thiz,jint count) { sem_t sem; if(sem_init(&sem,1,1)!=0) return; pthread_t pthreads[count]; for(int i=0;i<count;i++){ pthread_create(&pthreads[i],NULL,threadFunc,&sem); } for(int i=0;i<count;i++){ int retvalue=0; pthread_join(pthreads[i],(void**)&retvalue); if(retvalue!=0){ __android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred"); } } sem_destroy(&sem); }
結束語
本篇重點介紹了原生執行緒的基礎知識,包括原生執行緒需要用到的函式,原生執行緒的示例程式碼,以及原生程式碼使用Java執行緒進行執行緒同步等相關知識,相信大家學完本篇教程,都能熟練掌握所學的知識點,靈活運用到自己的實際開發中去。