Android NDK线程篇(四)

Android NDK线程篇

前言

本篇重点介绍原生线程的相关知识,包括线程基础知识,线程同步等,学完本篇,你将会对NDK原生线程有一个更加深入的认识。

线程基础

线程是进程并发执行多任务的机制,线程可以共享进程的各种资源,进程内的多个线程之间可以相互通信,也可以通过一定的方式进行线程,比如互斥锁,信号量等。

原生线程

我们可以通过Java线程来执行原生代码,也可以通过原生线程来执行。

Java线程

Java线程基础

我们可以通过Thread类来创建Java线程,也可以通过线程池来创建Java线程。

Java线程同步

本小节重点介绍原生代码使用Java对象进行线程同步。

原生代码可以通过MonitorEnterMonitorExit函数来使用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线程。POSIX线程简称pthreads

线程头文件

#include

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参数代表要传入线程可执行函数的参数

线程等待函数
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线程同步

POSIX线程目前支持两种线程同步方式,分别是互斥体和信号量,下面分别介绍这两种线程同步方式。

互斥体Mutex
头文件

#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;i        pthread_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);

}
信号量Semaphore
头文件

#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;i        pthread_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线程进行线程同步等相关知识,相信大家学完本篇教程,都能熟练掌握所学的知识点,灵活运用到自己的实际开发中去。

你可能感兴趣的:(android,NDK)