读写锁

先说点其他的,就是发现之前看的IPC(interprocess communication)资料是System V的(有点老旧,从博客中的书页截图就可以看出来,但是这本书的确不错),虽然说在我的最新版Ubuntu上还可以用,但我去看了POSIX和System V的区别好像POSIX更好一些,所以后面的IPC的学习就使用POSIX的。

1.概述

互斥锁将试图进入我们称之为临界区的所有其他线程都阻塞住。该临界区通常涉及这些线程共享的一个或者多个数据的访问或更新。然而有时候我们可以在读某个数据与修改某个数据之间作以区分。

读写锁的两条分配规则

  ①只要没有线程持有某个给定的读写锁用于写,那么任意数目的线程可以持有该读写锁用于读。

  ②仅当没有线程持有某个给定的读写锁用于读或用于写时,才能分配该读写锁用于写。

举个栗子,ATM机在没人用的时候大家可以围个圈去参观它,但是只有它在没人用它(参观的不算使用)时,其他人才可以用它。

某些应用中读数据比写数据频繁的多,这些应用可以从读写锁代替互斥锁中获益。任意给定时刻允许多个读出者存在提供了更高的并发度,同时在某个写入者修改数据期间保护该数据该数据,以免其他读者或写者干扰。

这种对于对某个给定资源的共享访问也称为 共享-独占  上锁。因为获取一个读写锁用于读称之为 共享锁,获取一个读写锁用于写称之为 独占锁。

2.获取与释放读写锁

读写锁的数据类型为pthread_rwlock_t。如果这个类型的某个变量是静态分配的,那么可通过给它赋常值 PTHREAD_RWLOCK_INITIALIZER 来初始化它。

 pthread_rwlock_rdlock获取一个读出锁,如果对应的读写锁已由某个写入者持有,那么久阻塞调用线程。pthread_rwlock_wrlock 获取一个写入锁,如果对应的写入锁已有另一个写入锁持有,或者已由一个或多个读出者持有,那就阻塞调用线程。pthread_rwlock_unlock 释放一个读出所或写入锁。

#include<pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_unlock(pthread_rwlock_t *rwptr);
//成功返回0,失败返回一个对应错误的正值

 下面两个函数尝试获取一个读出锁或写入锁,但是如果该锁不能马上取得,那就返回一个EBUSY错误,而不是把调用线程投入睡眠。

#include<pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwptr);
//成功返回0,失败返回一个对应错误的正值

 3.读写锁属性

除了使用静态分配的方法给读写锁初始化,还可以使用 pthread_rwlock_init 来动态地初始化。当一个线程不再需要某个读写锁时,可以调用 pthread_rwlock_destory 摧毁它。

#include<pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr);
int pthread-rwlock_destory(pthread_rwlock_t *rwptr);
//成功返回0,失败返回一个对应错误的正值

 数据类型为 pthread_rwlockattr_t的某个属性对象一旦初始化,就通过调用不同的函数来启用或者禁止特定属性。当前定义了唯一的属性是 PTHREAD_PROCESS_SHARED ,它指定相应的读写锁在不同进程间共享,而不仅仅是在单个进程内的不同线程间共享。以下两个函数分别获取和设置这个属性。

#include<pthread.h>
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, int *valptr);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int value);
//成功返回0,失败返回一个对应错误的正值

 第一个函数在由valptr指向的整数中返回该属性的当前值。第二个函数把该属性的当前值设置为value, 其值为 PTHREAD_PROXESS_PRIVATE,或者为 PTHREAD_PROCESS_SHARED。

 由于读写锁的特性,我设计了两个程序,测试其是否可以共读,写锁和读锁在同时竞争时,写锁是否有更高优先级。

例程1.

#include"main.h"
#include"time_rw.h"
#include"pthread_rwlock.h"

int main()
{
	pthread_t th1, th2, th3, th4, th5;
	Pthread_rwlock_init(&rw, NULL);
//	Pthread_create(&th1, &pthread1);
//	sleep(1);
//	Pthread_create(&th2, &pthread2);
	Pthread_create(&th3, &pthread3);
     sleep(1); Pthread_create(&th4, &pthread4); Pthread_create(&th5, &pthread5); sleep(15); }

 对程序先予以说明,线程1,2是给文件写的线程,线程3,4,5为读线程。

现在让线程3先创建,在其加锁后打印并休眠20秒。这时候如果线程4,5还可以访问,则说明其确实有共读性。

读写锁

 

 在线程3未解锁的情况下,线程4,5仍然可以查看文件内容,足以说明其共读性。

 

#include"main.h"
#include"time_rw.h"
#include"pthread_rwlock.h"

int main()
{
	pthread_t th1, th2, th3, th4, th5;
	Pthread_rwlock_init(&rw, NULL);
	Pthread_create(&th1, &pthread1);
	sleep(1);
	Pthread_create(&th2, &pthread2);
	Pthread_create(&th3, &pthread3);
	//sleep(1);
	//Pthread_create(&th4, &pthread4);
	//Pthread_create(&th5, &pthread5);
	sleep(15);
}

 现在先让线程1运行,线程1用完锁以后释放,让线程2和线程3争抢读写锁,发现因为线程2是写锁,看起来其在与读锁争抢时有更高的优先级

读写锁

 

 但是实际上我将线程2,3的创建顺序进行调换以后

读写锁

 

 发现并不是,其优先级与创建顺序有关?

 

上一篇:linux与线程


下一篇:线程同步之读写锁