以前在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) ;
}