(1) 线程互斥
对象 | 操作 | Linux Pthread API | Windows SDK 库对应 API |
线程 | 创建 | pthread_create | CreateThread |
退出 | pthread_exit | ThreadExit | |
等待 | pthread_join | WaitForSingleObject | |
互斥锁 | 创建 | pthread_mutex_init | CreateMutex |
销毁 | pthread_mutex_destroy | CloseHandle | |
加锁 | pthread_mutex_lock | WaitForSingleObject | |
解锁 | pthread_mutex_unlock | ReleaseMutex | |
条件 | 创建 | pthread_cond_init | CreateEvent |
销毁 | pthread_cond_destroy | CloseHandle | |
触发 | pthread_cond_signal | SetEvent | |
广播 | pthread_cond_broadcast | SetEvent / ResetEvent | |
等待 | pthread_cond_wait / pthread_cond_timedwait | SingleObjectAndWait |
pthread_mutex_init 函数原型:
pthread_mutex_init 初始化一个互斥锁 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 初始化互斥量 | |
函数原型 | int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr) | |
函数传入值 | mutex | 指向要初始化的互斥锁的指针 |
| ||
attr | 指向属性对象的指针,该属性对象定义要初始化的互斥锁的属性 | |
如果该指针为 NULL,则使用默认的属性。 | ||
默认使用PTHREAD_MUTEX_DEFAULT。 合法的类型属性值有: PTHREAD_MUTEX_NORMAL; PTHREAD_MUTEX_ERRORCHECK; PTHREAD_MUTEX_RECURSIVE; PTHREAD_MUTEX_DEFAULT。 |
函数返回值
成功:0
出错:返回错误码
错误代码
EAGAIN:系统缺少足够的资源去初始化其他的互斥量
ENOMEM:内存不足去初始化互斥量
EPERM:调用者没有执行该操作的权限
类型说明:
PTHREAD_MUTEX_NORMAL 快速互斥锁
这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起这个线程的死锁。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。
PTHREAD_MUTEX_ERRORCHECK 检错互斥锁
这种类型的互斥锁会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会返回一个错误代码。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。
PTHREAD_MUTEX_RECURSIVE 递归互斥锁
如果一个线程对这种类型的互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能得到这个互斥锁。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。这种类型的互斥锁只能是进程私有的(作用域属性为PTHREAD_PROCESS_PRIVATE)。
PTHREAD_MUTEX_DEFAULT 快速互斥锁
这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起不可预料的结果。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。POSIX标准规定,对于某一具体的实现,可以把这种类型的互斥锁定义为其他类型的互斥锁。
互斥锁可以分为快速互斥锁、递归互斥锁和检错互斥锁。这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时的是否需要阻塞等待。快速锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止。递归互斥锁能够成功地返回并且增加调用线程在互斥上加锁的次数,而检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息。
pthread_mutex_destroy 函数原型:
pthread_mutex_destroy 销毁一个互斥量 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 释放对互斥变量分配的资源 | |
函数原型 | int pthread_mutex_destroy(pthread_mutex_t *mutex) | |
函数传入值 | mutex | 要释放的互斥量参数 |
| ||
| ||
| ||
函数返回值 | 成功:返回0 | |
失败:返回错误码 | ||
错误代码 | EBUSY:检测到企图摧毁被锁定的通过mutex属性引用的目标 或者 被另一线程引用
EINVAL: 由mutex指定的值失效
|
pthread_mutex_lock函数原型:
pthread_mutex_lock 锁住一个互斥量 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 如果已经锁定了互斥对象,调用线程将阻塞,直到互斥锁解锁 | |
函数原型 | int pthread_mutex_lock(pthread_mutex_t *mutex) | |
函数传入值 | mutex | 指向需要获取互斥锁并给其上锁的结构的指针。 |
| ||
| ||
| ||
函数返回值 | 成功:返回0 | |
失败:返回错误码 | ||
错误代码 | EINVAL:互斥锁是由协议属性PTHREAD_PRIO_PROTECT指定
并且调用线程的优先级比mutex的当前优先级上限高
mutex指定的值不会引用一个初始化的互斥对象。
EAGAIN:由于超过递归锁的最大值导致互斥锁不能获取到
EDEADLK:当前线程已经拥有互斥锁
|
pthread_mutex_trylock函数原型:
pthread_mutex_trylock 锁住一个互斥量 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 试图根据mutex为其上互斥锁,如果其已经被上锁,则不会阻塞线程。 | |
函数原型 | int pthread_mutex_trylock(pthread_mutex_t *mutex) | |
函数传入值 | mutex | 指向需要获取互斥锁并给其上锁的结构的指针。 |
| ||
| ||
| ||
函数返回值 | 成功:返回0 | |
失败:返回错误码 | ||
错误代码 | EINVAL:互斥锁是由协议属性PTHREAD_PRIO_PROTECT指定
并且调用线程的优先级比mutex的当前优先级上限高
mutex指定的值不会引用一个初始化的互斥对象。
EAGAIN:由于超过递归锁的最大值导致互斥锁不能获取到
EDEADLK:当前线程已经拥有互斥锁
EBUSY:mutex不能被获取,由于它已经被锁
|
pthread_mutex_unlock函数原型:
pthread_mutex_unlock 锁住一个互斥量 | ||
所需头文件 | #include <pthread.h> | |
函数说明 | 根据mutex解锁互斥锁 | |
函数原型 | int pthread_mutex_unlock(pthread_mutex_t *mutex) | |
函数传入值 | mutex | 指向需要释放互斥锁并给其解锁的结构的指针。 |
| ||
| ||
| ||
函数返回值 | 成功:返回0 | |
失败:返回错误码 | ||
错误代码 | EINVAL:mutex指定的值不会引用一个初始化的互斥对象。
EAGAIN:由于超过递归锁的最大值导致互斥锁不能获取到
EPERM:当前线程内有自己的互斥锁
|
实验用例:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex ;
void *print_msg(void *arg){
int i=0;
pthread_mutex_lock(&mutex);
for(i=0;i<15;i++){
printf("output : %d\n",i);
usleep(100);
}
pthread_mutex_unlock(&mutex);
}
int main(int argc,char** argv){
pthread_t id1;
pthread_t id2;
pthread_mutex_init(&mutex,NULL);
pthread_create(&id1,NULL,print_msg,NULL);
pthread_create(&id2,NULL,print_msg,NULL);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_mutex_destroy(&mutex);
return 1;
}