- 通过为每种事件类型分配单独的处理线程,可以简化处理异步事件的代码。每个线程在进行事件处理时可以采用同步编程模式。
- 多个进程必须使用操作系统提供的复制机制才能实现内存和文件描述符的共享。而多个线程自动地可以访问相同的存储空间和文件描述符。
- 有些问题可以分解从而提高整个程序的吞吐量。将原来串行化执行的任务变成交叉进行,当然,这些任务必须相互独立、互不依赖。
- 交互的程序同样可以通过使用多线程来改善响应时间,多线程可以把程序中处理用户输入输出的部分与其他部分分开。
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
Returns: nonzero if equal, 0 otherwise
#include <pthread.h>
pthread_t pthread_self(void);
Returns: the thread ID of the calling thread
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
Returns: 0 if OK, error number on failure
- 线程可以简单地从启动例程中返回,返回值是线程的退出码
- 线程可以被同一进程中的其他线程取消
- 线程调用pthread_exit
#include <pthread.h>
void pthread_exit(void *rval_ptr);
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
Returns: 0 if OK, error number on failure
调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
- 如果线程从启动例程中返回,rval_ptr包含返回码
- 如果线程被取消,由rval_ptr指定的内存单元就设置为PTHREAD_CANCELED
- 如果线程调用pthread_exit,rval_ptr指向的内存单元作为返回值传递给调用pthread_join函数的其他线程
线程可以通过调用pthread_cancel函数来请求取消同一进程中的其他线程
#include <pthread.h>
int pthread_cancel(pthread_t tid);
Returns: 0 if OK, error number on failure
#include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);
线程清理处理程序
。
- 调用pthread_exit时
- 响应取消请求时
- 用非零execute参数调用pthread_cleanup_pop时(以0调用pthread_cleanup_pop函数时,清理函数不被调用)
#include <pthread.h>
int pthread_detach(pthread_t tid);
Returns: 0 if OK, error number on failure
在变量修改时间多于一个存储器访问周期的处理器结构中,当存储器读与存储器写这两个周期交叉时,这种不一致就会出现。
两个或多个线程试图在同一时间修改同一变量时,也需要进行同步。考虑变量增量操作的情况:
- 如果是静态分配的互斥量,可以把它设置为常量PTHREAD_MUTEX_INITIALIZER
- 如果是动态分配(通过malloc函数)的互斥量,可以通过调用函数pthread_mutex_init进行初始化;在释放内存前(通过free函数)需要调用pthread_mutex_destroy
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Both return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex); // 成功锁住返回0;锁住失败返回EBUSY,不会阻塞
int pthread_mutex_unlock(pthread_mutex_t *mutex);
All return: 0 if OK, error number on failure
#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr);
Returns: 0 if OK, error number on failure
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
Both return: 0 if OK, error number on failure
如果默认属性就足够的话,可以使用常量PTHREAD_RWLOCK_INITIALIZER对静态分配的读写锁进行初始化
在释放动态分配的读写锁占有内存之前,需要调用pthread_rwlock_destroy函数做清理工作。否则,会导致分配给该锁的资源丢失
#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
All return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
Both return: 0 if OK, error number on failure
#include <pthread.h>
#include <time.h>
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr);
Both return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
Both return: 0 if OK, error number on failure
- 如果条件变量是静态分配的,可以赋值为常量PTHREAD_COND_INITIALIZER
- 如果条件变量是动态分配的,需要使用函数pthread_cond_init对它进行初始化;在释放条件变量底层的内存空间之前,需要使用pthread_cond_destroy对条件变量反初始化
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict tsptr);
Both return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
Both return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);
Both return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
All return: 0 if OK, error number on failure
#include <pthread.h>
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);
Both return: 0 if OK, error number on failure
#include <pthread.h>
int pthread_barrier_wait(pthread_barrier_t *barrier);
Returns: 0 or PTHREAD_BARRIER_SERIAL_THREAD if OK, error number on failure