Linux多线程通信

线程控制

线程创建
  进程被创建时,系统会为其创建一个主线程,而要在进程中创建新的线程,则可以调用pthread_create:

pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(start_routine)(void*), void *arg);

start_routine为新线程的入口函数,arg为传递给start_routine的参数。
  每个线程都有自己的线程ID,以便在进程内区分。线程ID在pthread_create调用时回返给创建线程的调用者;一个线程也可以在创建后使用pthread_self()调用获取自己的线程ID:

pthread_self (void) ;

线程退出
  线程的退出方式有三:
  (1)执行完成后隐式退出;
  (2)由线程本身显示调用pthread_exit 函数退出;

pthread_exit (void * retval) ;

  (3)被其他线程用pthread_cancel函数终止:

pthread_cancel(pthread_t thread) ;

 

线程互斥

  互斥意味着“排它”,即两个线程不能同时进入被互斥保护的代码。Linux下可以通过pthread_mutex_t 定义互斥体机制完成多线程的互斥操作,该机制的作用是对某个需要互斥的部分,在进入时先得到互斥体,如果没有得到互斥体,表明互斥部分被其它线程拥有,此时欲获取互斥体的线程阻塞,直到拥有该互斥体的线程完成互斥部分的操作为止。
  下面的代码实现了对共享全局变量x 用互斥体mutex 进行保护的目的:
int x; // 进程中的全局变量
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL); //按缺省的属性初始化互斥体变量mutex
pthread_mutex_lock(&mutex); // 给互斥体变量加锁//对变量x 的操作
phtread_mutex_unlock(&mutex); // 给互斥体变量解除锁
 

线程同步

  同步就是线程等待某个事件的发生。只有当等待的事件发生线程才继续执行,否则线程挂起并放弃处理器。当多个线程协作时,相互作用的任务必须在一定的条件下同步。
  Linux下的C语言编程有多种线程同步机制,最典型的是条件变量(condition variable)。pthread_cond_init用来创建一个条件变量,其函数原型为:
pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);

 

pthread_cond_wait和pthread_cond_timedwait用来等待条件变量被设置,值得注意的是这两个等待调用需要一个已经上锁的互斥体mutex,这是为了防止在真正进入等待状态之前别的线程有可能设置该条件变量而产生竞争。pthread_cond_wait的函数原型为:
pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t *mutex, const struct timespec * abstime)

经历abstime段时间后,即使条件变量不满足,阻塞也被解除。

等待的时间通过abstime参数(绝对系统时间,过了该时刻就超时)指定,超时则返回ETIMEDOUT错误码。

 

pthread_cond_broadcast用于设置条件变量,即使得事件发生,这样等待该事件的线程将不再阻塞:

pthread_cond_broadcast (pthread_cond_t *cond) ;

 

pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。

但使用pthread_cond_signal不会有“惊群现象”产生,他最多只给一个线程发信号。假如有多个线程正在阻塞等待着这个条件变量的话,那么是根据各等待线程优先级的高低确定哪个线程接收到信号开始继续执行。如果各线程优先级相同,则根据等待时间的长短来确定哪个线程获得信号。但无论如何一个pthread_cond_signal调用最多发信一次。
pthread_cond_signal (pthread_cond_t *cond) ;

 

pthread_cond_destroy 则用于释放一个条件变量的资源。

用生产者与消费者的关系来看。
例如,有一个生产者,2个消费者。
//定义全局的 互斥对象和条件等待对象

 pthread_mutex_t mtx;
 pthread_cond_t   cond;

//消费者线程函数:
void threadproc(void * parm)
 {
   while(1)
   {
     pthread_mutex_lock(&mtx);//锁定mtx ,以防其他消费者线程 并发等待
     pthread_cond_wait(&cond,&mtx);//首先解锁mtx,让其消费者线程或者生产者线程 获得机会去执行。然后休眠,不消耗任何CPU时间,等待被生产者唤醒
    
     //...dosomthing

     pthread_mutex_unlock(&mtx);//解锁
   }
   pthread_exit(0);
 }

//生产者线程
void pdthreadproc(void * parm)
{
    while(1)
    {
       pthread_mutex_lock(&mtx);//锁定mtx ,以防其他消费者线程 并发等待
//...dosomthing pthread_cond_broadcast(&cond,&mtx);//唤醒所有消费者线程,再次锁定mtx pthread_mutex_unlock(&mtx);//解锁 } pthread_exit(0); }

pthread_cond_wait 未返回之前一直处于睡眠状态,那么当消费者线程被唤醒之后,它首先要去锁定mtx,获得独占权,其他线程干等!执行完毕之后再解锁,其他消费者线程 执行被唤醒之后的过程。

posted @ 2014-09-12 10:55  罗维  阅读(1042)  评论(0编辑  收藏  举报