在编写多线程时,有些公共数据修改的机会比较少,相对比较写它们读的机会返回很多,在读的过程中往往伴随查找的操作,中间耗时很长,给这种代码加锁反而会降低我们的效率,有一种方法专门处理这种问题,那就是——读写锁。
读写锁是一种特殊的自旋锁,它把对共享资源的访问者划分为读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。
自旋锁是专门为防止多处理器并发而引入的一种锁。自旋锁的初衷就是:在短时间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待重新可用的期间内进行自旋,所以自旋锁不应该被持有时间太长。二元信号量和互斥锁都称之为挂起等待锁。
我们来了解一下读写锁中的各个接口函数:
pthread_rwlock_destroy用来销毁一个读写锁,参数为自己定义的一个共享的变量的地址。
pthread_rwlock_init用来初始化一个读写锁,第一个参数同上,第二个参数设置为NULL,指缺省属性。
pthread_rwlock_rdlock是请求写的锁,参数为读写锁变量的地址。
pthread_rwlock_tryrdlock成功时返回0,失败时返回的是错误码。
pthread_rwlock_wrlock是请求读的锁,参数还是为读写锁变量的地址。
pthread_rwlock_trywrlock成功时返回的是0,失败时返回的是错误码。
不管是读锁还是写锁,释放锁都用的是pthread_rwlock_unlock函数。
下面用读写锁实现的读者写者问题中,写者每次对data进行加1操作,读者只需要读出data即可。读者与写者问题中,写者与写者之间是互斥关系,读者与读者之间没有关系,在同步与互斥的实现中,还有读者优先还是写者优先的问题。即当有读者正在读数据时,同时来了读者和写者,读者优先是指来的读者优先读,写者优先是指来的写者在当前读者读完时进去临界区进行写操作。
下面是三种结果,第一种是读者和写者之间没有任何一方sleep时的结果,当写者写完时读者进行读操作。
第二种是,当写者写的慢时,它能获得锁的机会就大大减少了,可见读者读的机会就多了。
第三种是,当读者读的慢时,它获得锁的机会大大减少了,而写者就会获得更多写的机会。