linux 下的多线程编程

Linux 下POSIX线程 

使用threadid标识一个线程。

创建线程的函数如下:

   1: #include <pthread.h>
   2:  
   3: int pthread_create(
   4:        pthread_t *restrict tidp,
   5:        const pthread_attr_t *restrict attr,
   6:        void *(*start_rtn)(void *), void *restrict arg);

 

判断两个线程是否相同

   1: #include <pthread.h>
   2:  
   3: int pthread_equal(pthread_t tid1, pthread_t tid2)

获取本线程的线程id

   1: #include <pthread.h>
   2:  
   3: pthread _t pthread_self(void);

线程终止

   1: #include <pthread.h>
   2:  
   3: void pthread_exit(void *rval_ptr);
   4:  
   5: int pthread_join(pthread_t thread, void **rval_ptr);

一个线程可以要求另外一个线程被终止:

   1: #include <pthread.h>
   2:  
   3: void pthread_cancel(pthread_t tid)

线程cacel的取消由state和type决定。相关函数如下:

   1: #include <pthread.h>
   2:      int pthread_setcancelstate(int state, int *oldstate);
   3:  
   4:      int pthread_setcanceltype(int type, int *oldtype);
   5:  
   6:      void pthread_testcancel(void);

pthread_setcancelstate 原子的设置线程的state,并返回之前的状态(oldstate)。可能取值为:PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DISABLE

pthread_setcanceltype 原子的设置线程的type,并返回之前的type。可能的取值为:PTHREAD_CANCEL_DEFERRED 和 PTHREAD_CANCEL_ASYNCHRONOUS

新创建的线程的state和type默认分别为PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DEFERRED

这些属性需要再开始设置,而不能在线程运行中修改。

 

   1: #include <pthread.h>
   2:  
   3: void pthread_cleanup_push(void (*rtn)(void *), void *arg);
   4: void pthread_cleanup_pop(int execute);

这两个函数维护一个函数指针的Stack,可以把函数指针和函数参数值push/pop。执行的顺序则是从栈顶到栈底,也就是和push的顺序相反。

在下面情况下pthread_cleanup_push所指定的thread cleanup handlers会被调用:

a. 调用pthread_exit

b. 相应cancel请求

c. 以非0参数调用pthread_cleanup_pop()。(如果以0调用pthread_cleanup_pop(),那么handler不会被调用

有一个比较怪异的要求是,由于这两个函数可能由宏的方式来实现,因此这两个函数的调用必须得是在同一个Scope之中,并且配对,因为在pthread_cleanup_push的实现中可能有一个{,而pthread_cleanup_pop可能有一个}。因此,一般情况下,这两个函数是用于处理意外情况用的,举例如下:

   1: void *thread_func(void *arg)
   2: {
   3:     pthread_cleanup_push(cleanup, “handler”)
   4:  
   5:     // do something
   6:  
   7:     Pthread_cleanup_pop(0);
   8:     return((void *)0);
   9: }

注: 个人测试,pthread_cleanup_push 和pthread_cleanup_pop的个数也要一致。

 

线程同步

互斥量Mutex

同一时刻只能有一个线程拿到锁

创建和关闭的方法:

   1: #include <pthread.h>
   2:  
   3: int pthread_mutex_init(
   4:        pthread_mutex_t *restrict mutex,
   5:        const pthread_mutexattr_t *restrict attr)
   6:  
   7: int pthread_mutex_destroy(pthread_mutex_t *mutex);

加锁解锁的方法:

   1: #include <pthread.h>
   2:  
   3: int pthread_mutex_lock(pthread_mutex_t *mutex);
   4:  
   5: int pthread_mutex_trylock(pthread_mutex_t *mutex);
   6:  
   7: int pthread_mutex_unlock(pthread_mutex_t *mutex);

 

读写锁

读写锁有三种状态

i. 一个或者多个线程获得读锁,其他线程无法获得写锁

ii. 一个线程获得写锁,其他线程无法获得读锁

iii. 没有线程获得此读写锁

 

创建和关闭的办法

   1: #include <pthread.h>
   2:  
   3: int pthread_rwlock_init(
   4:        pthread_rwlock_t *restrict rwlock,
   5:        const pthread_rwlockattr_t *restrict attr)
   6:  
   7: int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

 

加锁解锁的办法:

   1: #include <pthread.h>
   2:  
   3: int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
   4:  
   5: int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
   6:  
   7: int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
   8:  
   9: int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
  10:  
  11: int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

 

Conditional Variable

条件变量是使得线程等待在一个条件上,直到其他的线程触发条件满足。

条件必须被Mutex保护起来

b. 类型为:pthread_cond_t,必须被初始化为PTHREAD_COND_INITIALIZER(用于静态分配的条件,等价于pthread_cond_init(…, NULL))或者调用pthread_cond_init

创建和销毁的办法:

   1: #include <pthread.h>
   2:  
   3: int pthread_cond_init(
   4:        pthread_cond_t *restrict cond,
   5:        const pthread_condxattr_t *restrict attr)
   6:  
   7: int pthread_cond_destroy(pthread_cond_t *cond);

等待条件发生的方法:

   1: #include <pthread.h>
   2:  
   3: int pthread_cond_wait(
   4:        pthread_cond_t *restrict cond,
   5:        pthread_mutex_t *restrict mutex);
   6:  
   7: int pthread_cond_timedwait(
   8:        pthread_cond_t *restrict cond,
   9:        pthread_mutex_t *restrict mutex,
  10:        const struct timespec *restrict timeout);

pthread_cond_wait函数用于等待条件发生(=true)。pthread_cond_timedwait类似,只是当等待超时的时候返回一个错误值ETIMEDOUT。超时的时间用timespec结构指定。此外,两个函数都需要传入一个Mutex用于保护条件

等待时间的结构:

   1: struct timespec {
   2:        time_t tv_sec;       /* seconds */
   3:        long   tv_nsec;      /* nanoseconds */
   4: };

注意timespec的时间是绝对时间而非相对时间,因此需要先调用gettimeofday函数获得当前时间,再转换成timespec结构,加上偏移量。

 

通知条件满足的函数:

   1: #include <pthread.h>
   2:  
   3: int pthread_cond_signal(pthread_cond_t *cond);
   4:  
   5: int pthread_cond_broadcast(pthread_cond_t *cond);

两者的区别是前者会唤醒单个线程,而后者会唤醒多个线程。

 

 

refer:Linux Thread 介绍总结

http://www.cnblogs.com/zhenjing/archive/2010/12/27/cancel_thread.html

原文地址:https://www.cnblogs.com/lovemdx/p/3288392.html