看流星社区

 找回密码
 注册账号
查看: 1921|回复: 0

多线程编程读写锁

[复制链接]

该用户从未签到

发表于 2013-5-19 11:08:19 | 显示全部楼层 |阅读模式
读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

1、看你是在什么平台做开发,如果是最新的visual studio2005的话你可以使用SRWLock,和RITICAL_SECTION(关键段)差不过的功能,不同的是由程序员控制读写线程,如果是读线程,可以同时读取,如果是写线程,则其他线程挂起,写完后马上就可以读取
首先,需要一个SRWLOCK结构,然后调用InitializeSRWLock(PSWRLOCK srwLock)函数初始化这个结构

SRWLOCK srw;  
InitializeSRWLock(&srw);  

一旦初始化完成,就可以对写入线程调用AcquireSRWLockExclusive()函数和ReleaseSRWLockExclusive()函数

[cpp] view plaincopy
AcquireSRWLockExclusive(&srw);  
  
//...写入数据,写入东西的时候该线程独占,其他任何线程不可进入  
  
ReleaseSRWLockExclusive(&srw);  

对于只读线程可以调用AcquireSRWLockShared()函数和ReleaseSRWLockShared()函数,如下


AcquireSRWLockShared(&srw);  
//..读取数据,如果这时没有写入数据则多个读取线程可以进行  
ReleaseSRWLockShared)&srw);  

对于你所说的要写线程优先那么还可以使用条件变量的方法,具体做法可以参考msdn。


2、Slim读/写锁
    SRWLock的目的和关键段相同:对一个资源进行保护,不让其它线程访问它。但是,与关键段不同的是,SRWLock允许我们区分哪些想要读取资源的值的线程(读取者线程)和想要更新资源的值的线程(写入者线程)。让所有的读取者线程在同一时刻访问共享资源应该是可行的,这是因为仅仅读取资源的值并不存在破坏数据的风险。只有当写入者线程想要对资源进行更新的时候才需要进行同步。在这种情况下,写入者线程想要对资源进行更新的时候才需要进行同步。在这种情况下,写入者线程应该独占对资源的访问权:任何其它线程,无论是读取者线程还是写入者线程,都不允许访问资源。这就是SRWLock提供的全部功能。
    首先,我们需要分配一个SRWLOCK结构并用InitializeSRWLock函数对它进行初始化:
    VOID InitializeSRWLock(PSRWLOCK SRWLock);
    一旦SRWLock初始化完成之后,写入者线程就可以调用AcquireSRWLockExclusive,将SRWLOCK对象的地址作为参数传入,以尝试获得对被保护资源的独占访问权。
    VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);
    完成对资源的更新之后,应该调用ReleaseSRWLockExclusice,并将SRWLOCK对象的地址作为参数传入,这样就解除了对资源的锁定。
    VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);
    对读取者线程来说,同样有两个步骤,单调用的是下面两个新的函数:
    VOID AcquireSRWLockShared(PSRWLOCK SRWLock);
    VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);
    不存在用来删除或销毁SRWLOCK的函数,系统会自动执行清理工作。
    与关键段相比,SRWLock缺乏下面两个特性:


•不存在TryEnter(Shared/Exclusive)SRWLock 之类的函数:如果锁已经被占用,那么调用AcquireSRWLock(Shared/Exclusive) 会阻塞调用线程。
•不能递归地调用SRWLOCK。也就是说,一个线程不能为了多次写入资源而多次锁定资源,然后再多次调用ReleaseSRWLock* 来释放对资源的锁定。

    总结,如果希望在应用程序中得到最佳性能,那么首先应该尝试不要共享数据,然后依次使用volatile读取,volatile写入,Interlocked API,SRWLock以及关键段。当且仅当所有这些都不能满足要求的时候,再使用内核对象。因为每次等待和释放内核对象都需要在用户模式和内核模式之间切换,这种切换的CPU开销非常大。

4、boost库读写锁
#include <boost/thread.hpp>  
#include <boost/function.hpp>  
  
typedef boost::shared_lock<boost::shared_mutex> boost_share_lock;  
typedef boost::unique_lock<boost::shared_mutex> boost_unique_lock;  
  
//共享读控制锁  
boost::shared_mutex m_mutexResource;   
boost_share_lock lockReader(m_mutexResource);  
//...共享读代码  
  
//同步写控制锁  
boost_unique_lock lockWriter(m_mutexResource);  
//...同步写代码
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-15 21:37

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表