读写锁的实现

什么是读写锁:

读写锁实际是种特殊的旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进读访问,写者则需要对共享资源进写操作。这种锁相对于旋锁,能提并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最可能的读者数为实际的逻辑CPU数。写者是排他性的个读写锁同时只能有个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

相关函数为:

1.初始化和销毁读写锁
    对于读写锁变量的初始化可以有两种方式,一种是通过给一个静态分配的读写锁赋予常值PTHREAD_RWLOCK_INITIALIZER来初始化它,另 一种方法就是通过调用pthread_rwlock_init()来动态的初始化。而当某个线程不再需要读写锁的时候,可以通过调用 pthread_rwlock_destroy来销毁该锁。函数原型如下:

这两个函数如果执行成功均返回0,如果出错则返回错误码。
在释放某个读写锁占用的内存之前,要先通过pthread_rwlock_destroy对读写锁进行清理,释放由pthread_rwlock_init所分配的资源。
在初始化某个读写锁的时候,如果属性指针attr是个空指针的话,表示默认的属性;如果想要使用非默认属性,则要使用到下面的两个函数:
#include
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
int pthread_rwlockattr_destroy(pthread_rwlockatttr_t *attr);
这两个函数同样的,如果执行成功返回0,失败返回错误码。
这里还需要说明的是,当初始化读写锁完毕以后呢,该锁就处于一个非锁定状态。
数据类型为pthread_rwlockattr_t的某个属性对象一旦初始化了,就可以通过不同的函数调用来启用或者是禁用某个特定的属性。
2.获取和释放读写锁
读写锁的数据类型是pthread_rwlock_t,如果这个数据类型中的某个变量是静态分配的,那么可以通过给它赋予常值 PTHREAD_RWLOCK_INITIALIZAR来初始化它。pthread_rwlock_rdlock()用来获取读出锁,如果相应的读出锁已 经被某个写入者占有,那么就阻塞调用线程。pthread_rwlock_wrlock()用来获取一个写入锁,如果相应的写入锁已经被其它写入者或者一 个或多个读出者占有,那么就阻塞该调用线程;pthread_rwlock_unlock()用来释放一个读出或者写入锁。函数原型如下:

这三个函数若调用成功则返回0,失败就返回错误码。要注意的是其中获取锁的两个函数的操作都是阻塞操作,也就是说获取不到锁的话,那么调用线程不是立即返 回,而是阻塞执行。有写情况下,这种阻塞式的获取所得方式可能不是很适用,所以,接下来引入两个采用非阻塞方式获取读写锁的函数 pthread_rwlock_tryrdlock()和pthread_rwlock_trywrlock(),非阻塞方式下获取锁的时候,如果不能马 上获取到,就会立即返回一个EBUSY错误,而不是把调用线程投入到睡眠等待。函数原型如下:
#include
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwptr);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwptr);
同样地,这两个函数调用成功返回0,失败返回错误码。

下面举一个关于读写锁的小例子:

相关代码:

#include<stdio.h>
#include<pthread.h>

pthread_rwlock_t rwlock;

int buf;
void *reader(void *arg)
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("reader is reading:%d\n",buf);
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }
}

void *writer(void *arg)
{
    int i=0;
    while(1)
    {
        pthread_rwlock_wrlock(&rwlock);
        buf =i++;
        printf("writer:%d\n",buf);
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }
}

int main()
{
    pthread_t tid1,tid2,tid3;
    pthread_create(&tid1,NULL,writer,NULL);
    pthread_create(&tid2,NULL,reader,NULL);
    pthread_create(&tid3,NULL,reader,NULL);

    pthread_rwlock_init(&rwlock,NULL);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);

    return 0;
}

运行结果如下:

时间: 2024-11-06 03:52:52

读写锁的实现的相关文章

Java并发程序设计(15)并发锁之读写锁(续二)写锁降级

1.1.1. 读写锁应用之三写锁降级 ReentrantReadWriteLock还具有写锁降级的特点,而这跟可重入性有一些关系. (1)持有写锁时可以降级为读锁. (2)持有读锁时不能升级为写锁. ReentrantReadWriteLock和ReentrantLock相似的是都有一个特点,就是可重入.可重入指已经获取到锁的线程可以再次获取锁,保证lock和unlock的次数相同即可. package com.test.concurrence; import java.util.Random;

ReentrantReadWriteLock读写锁的使用2

本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 这一节我们做一个缓存系统. 在读本节前 请先阅读 ReentrantReadWriteLock读写锁的使用1 第一版 public class CacheDemo { private Map<String, Object> cache = new HashMap<String, Object>(); public static void main(String[] args) { CacheDem

深入浅出 Java Concurrency (13): 锁机制 part 8 读写锁 (ReentrantReadWriteLock) (1)[转]

从这一节开始介绍锁里面的最后一个工具:读写锁(ReadWriteLock). ReentrantLock 实现了标准的互斥操作,也就是一次只能有一个线程持有锁,也即所谓独占锁的概念.前面的章节中一直在强调这个特点.显然这个特点在一定程度上面减低了吞吐量,实际上独占锁是一种保守的锁策略,在这种情况下任何“读/读”,“写/读”,“写/写”操作都不能同时发生.但是同样需要强调的一个概念是,锁是有一定的开销的,当并发比较大的时候,锁的开销就比较客观了.所以如果可能的话就尽量少用锁,非要用锁的话就尝试看能

锁,同步,可重入锁,读写锁(转)

1.synchronized 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility). 1.1 原子性 原子性意味着个时刻,只有一个线程能够执行一段代码,这段代码通过一个monitor object保护.从而防止多个线程在更新共享状态时相互冲突. 1.2 可见性 可见性则更为微妙,它要对付内存缓存和编译器优化的各种反常行为.它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 . 作用:

linux 读写锁应用实例

转自:http://blog.csdn.net/dsg333/article/details/22113489 /*使用读写锁实现四个线程读写一段程序的实例,共创建了四个新的线程,其中两个线程用来读取数据,另外两个线程用来写入数据.在任意时刻,如果有一个线程在写数据,将阻塞所有其他线程的任何操作.*/#include <errno.h>#include <pthread.h>#include <stdio.h>#include <stdlib.h>#incl

读写锁ReadWriteLock和缓存实例

读写锁:多个读锁不互斥,读锁与些锁互斥,写锁与写锁互斥.即:读的时候不允许写,写的时候不允许读,可以同时读. synchronized关键字和普通的Lock构造的锁,会造成读与读之间的互斥,因此读写锁可提高性能. 例子1:三个线程同时对一个共享数据进行读写. import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantRea

Linux多线程实践(6) --Posix读写锁解决读者写者问题

Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthre

深入浅出 Java Concurrency (14): 锁机制 part 9 读写锁 (ReentrantReadWriteLock) (2)[转]

这一节主要是谈谈读写锁的实现. 上一节中提到,ReadWriteLock看起来有两个锁:readLock/writeLock.如果真的是两个锁的话,它们之间又是如何相互影响的呢? 事实上在ReentrantReadWriteLock里锁的实现是靠java.util.concurrent.locks.ReentrantReadWriteLock.Sync完成的.这个类看起来比较眼熟,实际上它是AQS的一个子类,这中类似的结构在CountDownLatch.ReentrantLock.Semapho

数据库读写锁的实现(C++)

一.基本概念 在数据库中,对某数据的两个基本操作为写和读,分布有两种锁控制:排它锁(X锁).共享锁(S锁). 排它锁(x锁):若事务T对数据D加X锁,则其它任何事务都不能再对D加任何类型的锁,直至T释放D上的X锁: 一般要求在修改数据前要向该数据加排它锁,所以排它锁又称为写锁. 共享锁(s锁):若事务T对数据D加S锁,则其它事务只能对D加S锁,而不能加X锁,直至T释放D上的S锁: 一般要求在读取数据前要向该数据加共享锁, 所以共享锁又称读锁. 程序所收到的请求包括以下五种:Start.End.X

Java并发程序设计(13)并发锁之读写锁

1.1.1. 读写锁的应用之一读写分离 读写锁ReentrantReadWriteLock相对于ReentrantLock在特定情况下能提高同步性能,这是因为读写锁有以下特点: (1)读和读可以同时进行. 这一点是ReentrantLock所没有的优点. (2)读和写不能同时进行. (3)写和写不能同时进行. 应用读写锁访问资源的代码如下所示. class MySharedResource { private ReadWriteLock lock = new ReentrantReadWrite