#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
typedef union
{
char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
int __align;
} pthread_mutexattr_t;
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
初始化与销毁互斥属性对象。
pthread_mutexattr_init以默认值初始化互斥属性对象。使用一个未初始化的互斥属性对象,将导致不确定性的行为。如果输入NULL,将使用默认的互斥属性值。pthread_mutexattr_destroy销毁指定的互斥属性对象。一个已销毁的对象可以被重新初始化。使用一个已销毁的互斥属性对象,将导致不确定的行为。该函数在LinuxThread环境中的实现不做任何事情。int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
int pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr, int *kind);
pthread_mutexattr_settype & pthread_mutexattr_gettypeint pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind);
在LinuxThread仅支持一个互斥属性mutex kind。该值有以下可选值。
PTHREAD_MUTEX_FAST_NP
快速互斥。默认值
PTHREAD_MUTEX_RECURSIVE_NP
递归互斥
PTHREAD_MUTEX_ERRORCHECK_NP带错误检查的互斥
后缀NP指示旋转是不可移植的(non-portable)
mutex kind用于决定在企图加锁一个已经处于锁定状态的的互斥时将如何做。
PTHREAD_MUTEX_FAST_NP将挂起当前线程。PTHREAD_MUTEX_ERRORCHECK_NP立即返回,并携带错误码EDEADLK。PTHREAD_MUTEX_RECURSIVE_NP立即返回,并携带成功运行的返回码int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init
如果参数为NULL,使用默认属性进行初始化。正常初始化后,互斥的状态变成已初始化且未锁定状态。
企图初始化一个已初始化的互斥对象,将导致不确定性行为。
宏PTHREAD_MUTEX_INITIALIZER亦能完成互斥的初始化,但其不做错误检查。
pthread_mutex_destroy
互斥被销毁后变成一个非法值。一个已销毁的互斥对象可被重新初始化。引用一个已销毁的互斥将出现不可预期的行为。
销毁一个未锁定且已初始化的互斥是安全的。企图销毁一个锁定状态或被引用(例如pthread_cond_timedwait或pthread_cond_wait)将导致不确定行为。
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
如果互斥锁已被另一个线程锁定,调用线程将阻塞直到互斥锁可用。
pthread_mutex_lock与pthread_mutex_trylock除加锁一个已经处于锁定状态的互斥时,前者进入阻塞状态,直接返回外,二者没区别。
使用互斥修改上一节中出错的样例,使其达到预期的效果。
使用流程
- 在每一个需要互斥的地方都需要先加锁,后解锁。
- 加锁解锁必须成对使用,否则可能造成死锁
- 最小代码块内进行加锁解锁,以提高程序运行效率
源码
#include
#include
#include
#include
pthread_mutex_t mutex;
int g_num = 0;
void *start_routine_01(void *ptr)
{
for (size_t i = 0; i < 10000; i++)
{
// 锁定最小单元
pthread_mutex_lock(&mutex); // 锁定
g_num++;
pthread_mutex_unlock(&mutex); // 解锁
}
return (void *)NULL;
}
void *start_routine_02(void *ptr)
{
for (size_t i = 0; i < 10000; i++)
{
// 锁定最小单元
pthread_mutex_lock(&mutex); // 锁定
g_num++;
pthread_mutex_unlock(&mutex); // 解锁
}
return (void *)NULL;
}
int main(int argc, char const *argv[])
{
pthread_mutexattr_t attr; // 定义互斥属性
pthread_mutexattr_init(&attr); // 初始化互斥属性
pthread_mutex_init(&mutex, &attr); // 初始化互斥
pthread_mutexattr_destroy(&attr); // 销毁互斥属性
pthread_t thread_id_01;
pthread_t thread_id_02;
pthread_create(&thread_id_01, NULL, start_routine_01, NULL);
pthread_create(&thread_id_01, NULL, start_routine_02, NULL);
pthread_join(thread_id_01, NULL);
pthread_join(thread_id_02, NULL);
printf("计算结果为: %d\n", g_num);
printf("主线程即将退出...\n");
pthread_mutex_destroy(&mutex); // 销毁互斥
exit(EXIT_SUCCESS);
}
结果
计算结果为: 20000
主线程即将退出…