pthread

linux多线程
内核线程, 运行在内核空间, 由内核来调度; 用户线程运行在用户空间, 由线程库来调度.
当进程的一个内核线程获得CPU的使用权时, 它就加载并运行一个用户线程. 内核线程相当于用户线程运行的容器
一个进程可以拥有M个内核线程和N个用户线程, 其中M<=N, M和N的比值往往是固定的
根据M:N, 线程的实现方式可以分为三种模式: 完全在用户空间实现, 完全由内核调度和双层调度
1:N -> 完全在用户空间实现的线程: 无须内核支持, 内核甚至不知道这些线程的存在, 线程库负责管理所有执行线程, 比如线程的优先级 时间片等
对于这种实现方式, 内核线程实际就是进程本身. 这种方式的
优点是: 创建和调度线程都无须内核的干预, 因此速度十分快, 并且由于它不占用额外的内核资源, 所有即使一个进程创建了很多线程, 也不会对系统性能造成明显的影响
缺点是: 对于多处理系统, 一个进程的多线程无法运行在不同的CPU上, 因此也无法发挥CPU的性能
(但内核任然是以进程作为最小单位来调度的, 一个进程的所有执行线程共享该进程的时间片)
1:1 -> 完全由内核调度: 优缺点和上面对调, 略
M:N -> 双层调度模式: 前两者的混合体, 结合了优点: 不但不会消耗过多的内核资源, 而且线程切换速度也较快, 同时可以充分的利用多处理器的优势.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pthread.h

线程的创建
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*(*start_rountine)(void*), void* arg)
thread是新线程的标识符, 通过它来引用新线程
attr设置线程的属性

线程安全干净的退出
int pthread_exit(void* retval)
通过retval返回退出信息

回收线程, 等待线程结束, 该函数会阻塞, 直到被回收的线程结束为止
int pthread_join(pthread_t thread, void** retval)
retval的退出信息:
pthread_join错误码 描述
EDEADLK 可能引起死锁
EINVAL 目标线程不可回收
ESRCH 目标线程不存在
1
2
3
4
5
6
7
8
9
取消线程
int pthread_cancel(pthread_t thread)
int pthread_setcancelstate(int state, int* oldstate) // 设置线程的取消状态 oldstate为原状态
int pthread_setcanceltype(int type, int* oldtype) // 设置线程的取消类型 oldtype为原类型
state:
PTHREAD_CANCEL_ENABLE: 允许线程被取消, 默认状态
PTHREAD_CALCEL_DISABLE: 禁止线程被取消, 此时若取消线程, 请求将被挂起知道该线程允许被取消
PTHREAD_CANCEL_ASYNCHRONOUS: 线程随时都可以被取消, 它将使得接收到的取消请求的目标线程立即采取行动
PTHREAD_CANCEL_DEFERRED: 延迟取消, 知道调用下面所谓的取消点函数中的一个: pthread_join pthread_testcancel pthread_cand_wait pthread_cond_timedwait sem_wait sigwait, 根据POSIX标准, 其他可能阻塞的系统调用, 比如read, write也都可以成为取消点, 但为了安全起见, 做好在可能被取消的代码中调用pthread_testcancel函数来设置取消点

线程属性: … 相应的有一梭子函数
typedef union{
char size[SIZEOF_PTHREAD_ATTR_T];
long ing _align;
} pthread_attr_t;

多线程同步机制: POSIX信号量 互斥量 条件变量
POSIX信号量: include <semaphore.h>
sem_init(sem_t sem, int pshared, unsigned int value)
int sem_destroy(sem_t
sem);
int sem_wait(sem_t sem);
int sem_trywait(sem_t
sem);
int sem_post(sem_t sem);
… 略
互斥锁
互斥所类型: pthread_mutex_t
互斥所的初始化方式:
int pthread_mutex_init(pthrad_mutex_t
mutex, const pthread_mutexattr_t* mutexattr)
特殊方式: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

互斥所销毁:
int pthread_mutex_destroy(pthread_mutex_t* mutex);

以原子操作的方式给一个互斥所加锁
int pthread_mutex_lock(pthread_mutex_t* mutex);

无论被操作的互斥所是否已经加锁, 它始终立即返回, 相当于上面的非阻塞版本
当目标互斥所未被加锁时, 它将进行加锁操作, 否则返回错误码EBUSY
int pthread_mutex_trylock(pthread_mutex_t* mutex);

解锁
int pthread_mutex_unlock(pthread_mutex_t* mutex);

互斥锁属性: 一抹多函数
常用属性
pshared:
PTHREAD_PROCESS_SHARED 互斥锁可以被跨进程共享
PTHREAD_PROCESS_PRIVATE 互斥锁只能被和锁的初始化线程隶属同一个进程的线程共享
type:
PTHREAD_MUTEX_NORMAL: 普通锁
PTHREAD_MUTEX_ERRORCHEDK: 检错锁
PTHREAD_MUTEX_RECURSIVE: 嵌套锁
PTHREAD_MUTEX_DEFAULT: 默认锁

条件变量
int pthread_cond_init(pthread_cond_t cond, const pthread_condattr_t cond_attr)
int pthread_cond_destroy(pthread_cond_t cond)
int pthread_cond_broadcast(pthread_cond_t
cond) // 广播唤醒所有等待目标条件的线程
int pthread_cond_signal(pthread_cond_t cond) // 唤醒一个等待目标的线程, 至于哪一个线程将被唤醒, 取决于线程的优先级和调度策略
int pthread_cond_wait(pthread_cond_t
cond) wait不会错过目标条件变量的任何变化

pthread_cond_t cond = PTHREAD_CAND_INITIALIZER;

0%