本篇重点介绍原生线程的相关知识,包括线程基础知识,线程同步等,学完本篇,你将会对NDK原生线程有一个更加深入的认识。
线程是进程并发执行多任务的机制,线程可以共享进程的各种资源,进程内的多个线程之间可以相互通信,也可以通过一定的方式进行线程,比如互斥锁,信号量等。
我们可以通过Java线程来执行原生代码,也可以通过原生线程来执行。
我们可以通过Thread类来创建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);
}
Android NDK的线程是通过POSIX标准实现的,所以也叫POSIX线程。POSIX线程简称pthreads
#include
int pthread_create(pthread_t *thread, pthread_attr_t const * attr, void *(*start_routine)(void *), void * arg);
函数解释:
thread参数代表pthread_t类型的线程指针
attr参数代表线程的属性指针
start_routine参数代表线程的执行函数的指针
arg参数代表要传入线程可执行函数的参数
int pthread_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__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线程目前支持两种线程同步方式,分别是互斥体和信号量,下面分别介绍这两种线程同步方式。
#include
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;ipthread_create(&pthreads[i],NULL,threadFunc,&pthread_mutex); } for(int i=0;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); }
#include
Semaphore初始化函数
extern int sem_init(sem_t *sem, int pshared, unsigned int value);
函数解释:
sem参数代表要创建的Semaphore指针
pshared参数代表要创建的Semaphore的数量
value代表要创建的Semaphore的初始数量
Semaphore获取函数
extern int sem_wait(sem_t *sem);
函数解释:
sem参数代表已创建的Semaphore指针
Semaphore释放函数
extern int sem_post(sem_t *sem);
函数解释:
sem参数代表已创建的Semaphore指针
Semaphore销毁函数
extern int sem_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;ipthread_create(&pthreads[i],NULL,threadFunc,&sem); } for(int i=0;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线程进行线程同步等相关知识,相信大家学完本篇教程,都能熟练掌握所学的知识点,灵活运用到自己的实际开发中去。