linux多线程-----同步机制(互斥量、读写锁、条件变量)

来源:互联网 发布:淘宝省市区街道联动 编辑:程序博客网 时间:2024/04/28 05:29


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);


1.pthread_mutex_lock函数对互斥量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 = 1After foo_hold, the fp->f_count = 2After foo_hold, the fp->f_count = 3After foo_rele, the fp->f_count = 2After foo_rele, the fp->f_count = 1last the referenceAfter 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多线程消费者和生产者模型实例(互斥锁和条件变量使用)


0 0
原创粉丝点击