全文内容来源于《UNIX环境高级编程-第三版》
#include
int pthread_create(pthread_t *restrict tidp,
const pthread_attr_t *restrict attr,
void *(*start_rtn)(void *),void *restrict arg);
成功则返回0,否则返回错误编号
tidp指向新创建的线程的线程ID
新创建的线程从函数start_rtn处执行,参数为arg
如果新线程在主线程调用pthread_create返回之前就运行了,那么新线程看到的是未经初始化的ntid的内容,这个内容就不是正确的线程ID
Linux线程ID是用无符号长整形来表示的,但是它们看起来像指针。
如果进程中的任意线程调用了exit,_Exit或者_exit,那么整个进程就会终止
单个线程可以通过3种方式退出,因此可以在不终止整个进程的情况下,停止它的控制流。、
#include
void pthread_exit(void *rval_ptr);
rval_ptr参数是一个无类型参数,与传给启动例程的单个参数类似
进程中的其它线程可以通过调用pthread_join()函数访问到这个指针。
#include
int pthread_join(pthread_t thread,void **rval_ptr);
成功则返回0,否则返回错误编号
调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果线程简单的从它的启动例程返回,rval_ptr就包含返回码。如果线程被取消,由rval_ptr指向的内存单元就设置为PTHREAD_CANCELED。
如果对线程的返回值并不感兴趣,可以把rval_ptr设置为NULL,这种情况下,调用pthread)joing函数可以等待指定的线程终止,但并不获取线程的终止状态。
#include
int pthread_cancel(pthread_t tid);
成功返回0,否则返回错误编号
其他线程调用这个函数,但是并不等待线程终止,它仅仅提出请求
#include
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
void pthread_cleanup_pop(int execute);
进程原语 | 线程原语 | 描述 |
---|---|---|
fork | pthread_create | 创建新的控制流 |
exit | pthread_exit | 从现有的控制流中退出 |
waitpid | pthread_join | 从控制流中得到退出状态 |
atexit | pthread_cancel_push | 注册到退出控制流中调用的函数 |
getpid | pthread_self | 获取控制流的ID |
abort | pthread_cancel | 请求控制流的非正常退出 |
#include
int pthread_detach(pthread_t tid);
要点:
对共享资源访问时,加一把锁,当其他线程试图访问时会阻塞,知道锁被释放,这时所有等待这个锁的线程都会变成可运行状态,首先获得资源的再加锁,这样其他线程再阻塞等待
#include
int phread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
成功则返回0,否则返回错误编号
静态分配的互斥量可以用THREAD_MUTEX_INITIALIZER初始化
pthread_mutex_t mutex = THREAD_MUTEX_INITIALIZER;
如果动态分配互斥量,在释放内存前需要调用上述destroy函数
使用下述函数加锁、解锁操作。
lock 加锁,如果已经上锁,阻塞。
unlock 解锁
trylock尝试加锁,不阻塞,如果之前已经加锁,返回EBUSY
#include
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
成功则返回0,否则返回错误编号
死锁问题
pthread_mutex_timedlock与phread_mutex_lock基本上是等价的。但是在达到超时时间值时,pthread_mutex_timedlock不会对互斥量进行加锁,而是返回错误码ETIMEOUT。使用绝对时间,timespec结构
#include
#include
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
const struct timespec *restrict tsptr);
#include
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
成功则返回0,否则返回错误编号
#include
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock);
成功则返回0,否则返回错误编号
#include
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
int pthread_cond_timtdwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex
const struct timespec *resitrct tsptr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
屏障是用户协调多个线程并行工作的同步机制,屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后从该点继续执行。
#include
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
const pthread_barrierattr_t *restrict attr,
unsigned int count );
int pthread_barrier_destroy(pthread_barrier_t *barrier);