linux多线程同步机制主要有:互斥量,读写锁,条件变量。
互斥量:
互斥量用pthread_mutex_t数据类型表示,在使用互斥变量以前,必须对它进行初始化,可以把它设置为PTHREAD_MUTEX_INITIALIZER(只是针对静态分配的互斥量),pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
也可以通过函数int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);进行初始化。
pthread_mutex_destroy destroys a mutex object, freeing the resources it might hold. The mutex must be unlocked on entrance.
In the LinuxThreads implementation, no resources are associated with mutex objects, thus pthread_mutex_destroy actually does
nothing except checking that the mutex is unlocked.
man手册关于pthread_mutex_destroy的介绍就是说在linux下线程的实现没有关于互斥量对象的资源,所以pthread_mutex_destroy仅仅是确认一下
互斥量mutex是处于解锁的状态。
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
2.pthread_mutex_unlock函数是对互斥量mutex进行解锁。
3.pthread_mutex_trylock函数尝试对互斥量mutex进行加锁,如果互斥量mutex处于未被锁住的状态,则将锁住该互斥量并返回0。如果互斥量mutex处于锁住的状态,则不能锁住该互斥量并返回EBUSY。
例子1:对互斥量加上引用计数机制,自己构造结构体。当最后一个引用被释放的时候,对象所占用空间也被释放。如下所示:
/*************************************************************************
> File Name: mutex_11_5.c
> Author:
> Mail:
> Created Time: 2016年03月23日 星期三 20时41分26秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct foo{
int f_count;
pthread_mutex_t f_lock;
};
//创建并初始化一个带有引用计数的互斥量
struct foo * foo_alloc(void)
{
struct foo * fp;
if((fp = malloc(sizeof(struct foo))) != NULL){
fp->f_count = 1;
if(pthread_mutex_init(&fp->f_lock, NULL) != 0){
free(fp);
return NULL;
}
}
return fp;
}
//对互斥量增加一个引用计数
void foo_hold(struct foo* fp)
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
//对互斥量减少一个引用计数
void foo_rele(struct foo* fp)
{
pthread_mutex_lock(&fp->f_lock);
if(--fp->f_count == 0){//最后一个引用了
printf("last the reference\n");
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destroy(&fp->f_lock);
free(fp);
}
else{
pthread_mutex_unlock(&fp->f_lock);
}
}
int main()
{
struct foo * fp;
if((fp = foo_alloc()) == NULL){
printf("foo_alloc error\n");
return -1;
}
printf("After foo_alloc, the fp->f_count = %d\n", fp->f_count);
foo_hold(fp);
printf("After foo_hold, the fp->f_count = %d\n", fp->f_count);
foo_hold(fp);
printf("After foo_hold, the fp->f_count = %d\n", fp->f_count);
foo_rele(fp);
printf("After foo_rele, the fp->f_count = %d\n", fp->f_count);
foo_rele(fp);
printf("After foo_rele, the fp->f_count = %d\n", fp->f_count);
foo_rele(fp);
printf("After foo_rele, the fp->f_count = %d\n", fp->f_count);
return 0;
}
输出:
After foo_alloc, the fp->f_count = 1
After foo_hold, the fp->f_count = 2
After foo_hold, the fp->f_count = 3
After foo_rele, the fp->f_count = 2
After foo_rele, the fp->f_count = 1
last the reference
After foo_rele, the fp->f_count = 0
读写锁(也叫做共享-独占锁):
读写锁和互斥锁类似,但是读写锁允许更高的并发性。互斥锁只有两种状态:加锁状态、不加锁状态;
读写锁有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态;
一次只能有一个线程占有写模式下的读写锁,但是可以允许多个线程占用读模式下的读写锁。
读写锁非常适用于对数据结构读的次数远大于写的情况。
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//对读写锁进行初始化
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);//释放为读写锁分配的资源
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//在读模式下获得读写锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//在写模式下获得读写锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);//尝试在读模式下获得读写锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);//尝试在写模式下获得读写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//对读写锁进行解锁
条件变量:
条件变量是线程可以使用的另一种同步机制。条件变量与互斥量一起使用的时候,允许线程以无竞争的方式等待特定的条件发生。条件本身是由互斥量保护的。线程在改变条件变量状态前必须先锁住互斥量。
条件变量在使用前必须初始化,一种是静态初始化:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
另一种是动态分配的条件变量,则用pthread_cond_init函数进行初始化。
在释放底层的内存空间之前,可以使用pthread_cond_destroy对条件变量进行去初始化。
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);//唤醒等待该条件变量上的某个线程
int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒等待该条件变量上的所有线程
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
线程调用pthread_cond_wait这个函数之后,内核会做下面这些事:
1,拿到锁的线程,把锁暂时释放;
2,线程休眠,进行等待;
3,线程等待通知,要醒来。(重新获取锁)
pthread_cond_timedwait函数功能和pthread_cond_wait类似,只是多了一个等待时间abstime的限制。
条件变量的使用参考博客: Linux多线程消费者和生产者模型实例(互斥锁和条件变量使用)