以前在Windows编写过很多多线程的应用程序,对于多线程的编写原理比较熟悉,但是在Linux很少真正用多线程编写过应用,Linux下多线程库pthread使用与Windows上多线程使用有不少差别,个人感觉Windows设计的线程库比较人性化,对使用者来说很容易掌握,但是在灵活性方面不如Linux。
下面就是一个使用pthread库编写的一个简单多线程demo,实现同时启动两个线程的功能,代码如下:
#include <stdio.h> #include <pthread.h> int count=0 ; pthread_mutex_t mutex ; pthread_mutex_t wait_all_start; pthread_cond_t condition ; pthread_t thrd1 ; pthread_t thrd2 ; bool all_threads_start=false ; bool b_thrd1_ready=false ; bool b_thrd2_ready=false ; void *thread_fun1(void *param) { b_thrd1_ready=true ; /*注意信号等待的用法,需要使用一个与被保护变量相同的互斥量*/ pthread_mutex_lock(&wait_all_start) ; while(!all_threads_start){//防止被干扰信号唤醒 pthread_cond_wait(&condition,&wait_all_start) ; } pthread_mutex_unlock(&wait_all_start) ; int a=0 ; while(a++!=10) { pthread_mutex_lock(&mutex) ; printf("%s:count=%d\n",__func__,count++) ; pthread_mutex_unlock(&mutex) ; Sleep(100); } } void *thread_fun2(void *param) { b_thrd2_ready=true ; pthread_mutex_lock(&wait_all_start) ; while(!all_threads_start){ pthread_cond_wait(&condition,&wait_all_start) ; } pthread_mutex_unlock(&wait_all_start) ; int a=0 ; while(a++!=10) { pthread_mutex_lock(&mutex) ; printf("%s:count=%d\n",__func__,count++) ; pthread_mutex_unlock(&mutex) ; Sleep(100) ; } } int main() { pthread_mutex_init(&mutex,NULL) ; pthread_mutex_init(&wait_all_start ,NULL) ; pthread_cond_init(&condition,NULL) ; b_thrd1_ready=false ; b_thrd2_ready=false ; all_threads_start=false ; if(pthread_create(&thrd1,NULL,thread_fun1,NULL)!=0){ printf("Create Thread 1 Failed!\n") ; return -1 ; } if(pthread_create(&thrd2,NULL,thread_fun2,NULL)!=0){ printf("Create Thread 2 Failed!\n") ; return -1 ; } printf("Create two thread done.....\n") ; while(true){/*等待需要唤醒的条件,防止在等待线程等待之前,就执行下去,注意下面发送信号的用法,使用if*/ pthread_mutex_lock(&wait_all_start) ; printf("main thread......\n") ; if(b_thrd1_ready&&b_thrd2_ready){//等待,确保两个线程都进入等待状态 printf("all threads ready......\n") ; all_threads_start=true ; pthread_cond_broadcast(&condition); //pthread_cond_signal(&condition) ; pthread_mutex_unlock(&wait_all_start) ;//注意这里别忘记了 break ; } Sleep(10) ; pthread_mutex_unlock(&wait_all_start) ; } pthread_join(thrd1,NULL) ; pthread_join(thrd2,NULL) ; printf("\ncount=%d\n",count) ; return 0 ; }
在使用pthread线程库时,需要注意一下几点:
1、互斥锁pthread_mutex_t只能本线程解锁,即如果在本线程中使用pthread_mutex_lock,就必须在本线程中使用pthread_mutex_unlock解锁;这也是在线程同步中与信号量的区别,信号量可以在不同的线程中加锁和解锁
2、使用条件变量pthread_cond_t,在调用pthread_cond_wait的时候需要传入一个互斥锁,当进入这个pthread_cond_wait函数内部时,会对这个这个互斥锁执行解锁操作,等待其他线程修改等待的条件,当条件满足被其他线程唤醒时,这个函数会执行加锁操作。
3、pthread_cont_wait这个函数有可能被其他干扰唤醒;比如说pthread_cond_signal有可能唤醒多个线程;
4、pthread_cond_signal函数在执行唤醒操作是一瞬间的,此时不管有没有线程在等待,这个信号都会消失,如果有线程等待就会唤醒该线程,如果此时没有线程进入等待状态,在此后有线程进入等待状态,这个信号也将无效;
为了避免上面3、4点,一般使用信号量等待和释放的模式是这样的:
等待线程使用模式:
pthread_mutex_lock(&xxxmutex) ; while(b_xxx_flag) pthread_cond_wait(&xxxcond,&xxxmutex); pthread_mutex_unlock(&xxxmutex)
信号发送线程使用模式:
while(true){ pthread_mutex_lock(&xxxmutex) ; if(b_ready){ b_xxx_flag=true ; pthread_cond_signal(&xxxcond) ; pthread_mutex_unlock(&xxxmutex) ; break ; } pthread_mutex_unlock(&xxxmutex) ; }