二:读写锁
互斥锁把试图进入我们称之为临界去的所有其他线程都阻塞住了,而读写锁则分两种情况
(1)只要没有线程只有某个给定的读写锁用于写,那么任意数目的线程可以持有该读写锁用于读。
(2)仅当没有线程持有某个给定的读写锁用于读或者写,才能分配该读写锁用于写。
只要没有线程在修改某个给定的数据,那么任意数目的线程都是可以拥有读访问权限,仅当没有其他线程读或者修改某个给定的数据的时候,当钱线程才能修改他。
这个对于某个给定资源的共享访问也称为共享-独占上锁,因为获取一个读写锁用于读称为共享锁,获取一个读写锁用于写称为独占锁。多读出者--单写入者
1:获取和释放读写锁
- #include<pthread.h>
- int pthread_rwlock_rdlock(pthread_wrlock_t *rw)
- int pthread_rwlock_wrlock(pthread_rwlock_t *rw)
- int pthread_rwlock_unlock(pthread_rwlock_t *rw)
下面给出尝试获取一个读出或写入锁,但是如果不能马上获取,就返回一个EBUSY错误,而不是把调用线程投入睡眠
- #include<pthread.h>
- int pthread_rwlock_tryrdlock(pthread_rwlock_t *rw);
- int pthread_rwlock_trywrlock(pthread_rwlock_t *rw);
2:读写锁的属性
静态初始化:PTHREAD——RWLOCK——INITIALIZER
动态初始化以及摧毁
- #include<pthread.h>
- int pthread_rwlock_init(pthread_rwlock_t *rw);
- int pthread_rwlock_destory(pthread_rwlock_t *rw);
初始化某个读写锁时候,如果attr是个空指针,则使用默认属性,要赋予它非默认属性,则是永下面两个函数
- #include<pthread.h>
- int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
- int pthread_rwlockattr_destory(pthread_rwlockattr_t *attr);
当前定义的唯一属性是PTHREAD——PROCESS——SHARED,它制定相应的读写锁将在不同进程间共享,而不仅仅在一个进程的各个线程内进行共享。
以下函数获取和设置这个属性:
- #include<pthread.h>
- int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr,int *valptr);
- int pthread_rwlockattr_setpshared(const pthread_rwlockattr_t *attr,int *value);
第一个函数在由valptr指向的证书中返回该属性的当前值,第二个函数把该属性的当前值设置为value,其值为PTHREAD_PROCESS_PRIVATE,或者PTHREAD_PROCESS_SHARED
这里有个结构体不得不说:
- typedef struct
- {
- pthread_mutex_t rw_mutex;
- pthread_cond_t rw_condreaders;
- pthread_cond_t rw_condwriters;
- int rw_magic;
- int rw_nwaitreaders;
- int rw_nwaitwriters;
- int rw_refcount;
- }pthread_rwlock_t;
初始化成功后,标志成员rw_magic就被设置成RW_MAGIC,所有函数都测试该成员,以检测调用这是否向某个已经初始化的读写锁传递指针,读写锁被摧毁后,这个成员被置为0
rw_refcount=-1:这是一个写入锁
rw_refcount=0:这个锁可用
rw_refcount>0:当前容纳着多少个读出锁
3:线程取消
如果pthread_rwlock_rdlock的调用线程阻塞在其中的pthread_cond_wait调用上并随后被取消,它就在扔持有互斥锁的情况下种植。通过对方调用函数pthread_cancel()一个线程可以被同一个进程内的任何其他线程锁取消,唯一参数是线程ID
- #include<pthread.h>
- int pthread_cancel(pthread_t tid);
- void pthread_cleanup_push(void(*function)(void *),void *arg);
- void pthread_cleanup_pop(int execute);
处理程序就是发生以下情况时候被调用的函数:
(1)调用线程被取消(pthread_cancel())
(2)调用线程自愿终止(pthread_exit())
pthread_cleanup_push的function参数是调用线程被取消时候锁调用的函数的地址,arg是它单个参数。pthread_cleanup_pop总是删除调用线程的取消清理栈中位于栈顶的函数,而且如果execute部位0,那就调用该函数。
- #include<pthread.h>
- #include "pthread_rwlock.h"
- pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER;
- pthread_t tid1,tid2;
- void *thread1(void *)
- {
- pthread_rwlock_rdlock(&rwlock);
- printf("thread1 got a read lock!\n");
- sleep(3);
- pthread_cancel(tid2);
- sleep(3);
- pthread_rwlock_unlock(&rwlock);
- return NULL;
- }
- void *thread2(void *arg)
- {
- printf("thread2 tries to obtains write lock!\n");
- pthread_rwlock_wrlock(&rwlock);
- printf("thread2 got a write lock");
- sleep(1);
- pthread_rwlock_unlock(&rwlock);
- return NULL;
- }
- int main(int argc,char *argv[])
- {
- void *status;
- pthread_setconcurrency(2); pthread_create(&tid1,NULL,thread1,NULL);
- sleep(1);
- pthread_create(&tid2,NULL,thread2,NULL);
- pthread_join(tid2,&status);
- if(status!=PTHREAD_CANCLED)
- printf("thread2 status=%p\n",status);
- pthread(tid1,&status);
- if(status!=NULL)
- printf("thread1 status=%p\n",status);
- printf("rw_refcount=%d,rw_nwaitreaders=%d,rw_nwaitwriters=%d\n",rwlock.rw_refcount,rwlock.rw_nwaitreaders,rwlock/rw_nwaitwriters);
- pthread_rwlock_destroy(&rwlock);
- exit(0);
- sleep(1);
- }
本程序第二个线程试图获取一个写入锁,可是这个不可能因为这个时候,第一个线程已经获取一个读出锁了,则底下部分都不被执行。
阅读(2423) | 评论(0) | 转发(0) |