本论坛为只读模式,仅供查阅,不能注册新用户,不能发帖/回帖,有问题可发邮件 xikug.xp (^) gmail.com
楼主: KiCall

读写锁 [复制链接]

Rank: 2

发表于 2012-3-9 22:27:53 |显示全部楼层
eaglenet 发表于 2012-3-9 22:21
您真理想化啊..代码编写的时候有极大可能在拿到写锁的情况下去操作一些原先要求拿读锁的情况. ...

写锁是独占的
请举例说明,何时会要求“独占的时候,再要转成共享锁,并且不允许在转成共享锁前被另一个独占锁请求抢占”。。。。。。。。

Rank: 1

发表于 2012-3-9 22:28:40 |显示全部楼层
KiCall 发表于 2012-3-9 20:45
关于读写锁
你说没必要使用,这个估计你没有遇到过每秒10万次以上的并发的情况。
就为了偶尔几次的写操作 ...

哎...我不是反对不要读写锁,而是想告诉你,在用读写锁的时候,要确定是不是锁阻碍了你的并发.如果不是,就别用..你也知道,读写锁是用在单写多读的情况下。有的时候适得其反.

Rank: 1

发表于 2012-3-9 22:31:08 |显示全部楼层
看主题

Rank: 1

发表于 2012-3-9 22:31:37 |显示全部楼层
本帖最后由 eaglenet 于 2012-3-9 22:36 编辑
KiCall 发表于 2012-3-9 20:52
先看清楚。。。。说的是使用临界体的情况。
很多人认为别人使用事件,互斥体等,理论上,性能低于临界体 ...


诸位,我第一次听说“临界体的获取和释放必须在同一个线程”这种事情..诸位大哥,我被这哥们打败了,KiCall,我认输! 诸位打酱油的哥们,走得时候把我尸体帮忙收拾了...

--------
我再加一条,临界体的获取和释放保持配对就OK了..我想KiCall可能没说清楚.

Rank: 1

发表于 2012-3-9 22:42:19 |显示全部楼层
KiCall 发表于 2012-3-9 22:27
写锁是独占的
请举例说明,何时会要求“独占的时候,再要转成共享锁,并且不允许在转成共享锁前被另一个 ...

我就不说,你这么自信,就希望你能在你今后的工作中,让你实现的读写锁插满各个软件代码领地..来证明你的正确。

Rank: 1

发表于 2012-3-9 22:44:11 |显示全部楼层
不就是想支持大并发么。通过拼命抢夺一个资源的利用来提高并发量是非常有局限的,把读写分开,考虑多空间和利用CPU原子操作性来解决。eaglenet真可怜,哈哈哈

Rank: 1

发表于 2012-3-9 22:49:33 |显示全部楼层
Cyg07 发表于 2012-3-9 22:44
不就是想支持大并发么。通过拼命抢夺一个资源的利用来提高并发量是非常有局限的,把读写分开,考虑多空间和 ...

我太苦逼了...

Rank: 2

发表于 2012-3-9 23:08:32 |显示全部楼层
KiCall 发表于 2012-3-9 22:27
写锁是独占的
请举例说明,何时会要求“独占的时候,再要转成共享锁,并且不允许在转成共享锁前被另一个 ...

而且
真的要实现转换
也不是什么麻烦的事情
  1. // RWLock.cpp : 定义 DLL 应用程序的导出函数。
  2. //
  3. #include "stdafx.h"
  4. #include <stdlib.h>
  5. #include "RWLock.h"

  6. PVOID __stdcall CreateRWLock()
  7. {
  8.         PRW_LOCK pLock=NULL;

  9.         do
  10.         {
  11.                 pLock=(PRW_LOCK)malloc(sizeof(RW_LOCK));

  12.                 if (!pLock)
  13.                 {
  14.                         break;
  15.                 }

  16.                 RtlZeroMemory(pLock,sizeof(RW_LOCK));

  17.                 pLock->iNowReaderCount=0;

  18.                 pLock->hShareLock=CreateEvent(NULL,FALSE,TRUE,NULL);

  19.                 if (pLock->hShareLock)
  20.                 {
  21.                         InitializeCriticalSection(&pLock->ExclusiveLock);

  22.                         InitializeCriticalSection(&pLock->ShareReaderCountLock);

  23.                         InitializeCriticalSection(&pLock->WriterLock);
  24.                 }else
  25.                 {

  26.                         free(pLock);

  27.                         pLock=NULL;
  28.                 }
  29.         } while (FALSE);

  30.         return (PVOID)pLock;
  31. }

  32. VOID __stdcall DeleteRWLock(PVOID pLock)
  33. {
  34.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  35.         if (pRwLock->hShareLock)
  36.         {
  37.                 DeleteCriticalSection(&pRwLock->ExclusiveLock);

  38.                 DeleteCriticalSection(&pRwLock->ShareReaderCountLock);

  39.                 CloseHandle(pRwLock->hShareLock);

  40.                 free(pLock);
  41.         }
  42. }

  43. VOID __stdcall AcquireShareLock(PVOID pLock)
  44. {
  45.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  46.         EnterCriticalSection(&pRwLock->ExclusiveLock);

  47.         EnterCriticalSection(&pRwLock->ShareReaderCountLock);

  48.         pRwLock->iNowReaderCount ++;

  49.         if( pRwLock->iNowReaderCount == 1 )
  50.         {
  51.                 WaitForSingleObject(pRwLock->hShareLock,INFINITE);
  52.         }

  53.         LeaveCriticalSection(&pRwLock->ShareReaderCountLock);

  54.         LeaveCriticalSection(&pRwLock->ExclusiveLock);
  55. }

  56. BOOL __stdcall TryAcquireShareLock(PVOID pLock)
  57. {
  58.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  59.         BOOL bIsAcquired=FALSE;

  60.         do
  61.         {
  62.                 bIsAcquired=TryEnterCriticalSection(&pRwLock->ExclusiveLock);

  63.                 if (!bIsAcquired)
  64.                 {
  65.                         break;
  66.                 }

  67.                 EnterCriticalSection(&pRwLock->ShareReaderCountLock);

  68.                 pRwLock->iNowReaderCount ++;

  69.                 if( pRwLock->iNowReaderCount == 1 )
  70.                 {
  71.                         WaitForSingleObject(pRwLock->hShareLock,INFINITE);
  72.                 }

  73.                 LeaveCriticalSection(&pRwLock->ShareReaderCountLock);

  74.                 LeaveCriticalSection(&pRwLock->ExclusiveLock);

  75.         } while (FALSE);

  76.         return bIsAcquired;
  77. }

  78. VOID __stdcall ReleaseShareLock(PVOID pLock)
  79. {
  80.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  81.         EnterCriticalSection(&pRwLock->ShareReaderCountLock);

  82.         pRwLock->iNowReaderCount --;

  83.         if( pRwLock->iNowReaderCount == 0 )
  84.         {
  85.                 SetEvent(pRwLock->hShareLock);
  86.         }

  87.         LeaveCriticalSection(&pRwLock->ShareReaderCountLock);
  88. }

  89. VOID __stdcall AcquireExclusiveLock(PVOID pLock)
  90. {
  91.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  92.         EnterCriticalSection(&pRwLock->WriterLock);

  93.         EnterCriticalSection(&pRwLock->ExclusiveLock);

  94.         WaitForSingleObject(pRwLock->hShareLock,INFINITE);
  95. }

  96. BOOL __stdcall TryAcquireExclusiveLock(PVOID pLock)
  97. {
  98.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  99.         BOOL bIsAcquired=FALSE;

  100.         do
  101.         {
  102.                 bIsAcquired=TryEnterCriticalSection(&pRwLock->WriterLock);

  103.                 if (!bIsAcquired)
  104.                 {
  105.                         break;
  106.                 }

  107.                 bIsAcquired=TryEnterCriticalSection(&pRwLock->ExclusiveLock);

  108.                 if (!bIsAcquired)
  109.                 {
  110.                         LeaveCriticalSection(&pRwLock->WriterLock);

  111.                         break;
  112.                 }

  113.                 WaitForSingleObject(pRwLock->hShareLock,INFINITE);
  114.         } while (FALSE);

  115.         return bIsAcquired;
  116. }

  117. VOID ConvertExclusiveToShare(PVOID pLock)
  118. {
  119.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  120.         pRwLock->iNowReaderCount++;

  121.         LeaveCriticalSection(&pRwLock->WriterLock);

  122.         LeaveCriticalSection(&pRwLock->ExclusiveLock);
  123. }

  124. VOID __stdcall ReleaseExclusiveLock(PVOID pLock)
  125. {
  126.         PRW_LOCK pRwLock=(PRW_LOCK)pLock;

  127.         LeaveCriticalSection(&pRwLock->WriterLock);

  128.         SetEvent(pRwLock->hShareLock);

  129.         LeaveCriticalSection(&pRwLock->ExclusiveLock);
  130. }

  131. 头文件:

  132. #ifndef _RWLOCK_H_
  133. #define _RWLOCK_H_

  134. typedef struct _RW_LOCK
  135. {
  136.         INT iNowReaderCount; //读者计数

  137.         CRITICAL_SECTION ExclusiveLock; //写锁

  138.         HANDLE hShareLock; //读锁

  139.         CRITICAL_SECTION ShareReaderCountLock; //读者计数访问互斥锁

  140.         CRITICAL_SECTION WriterLock;
  141. }RW_LOCK,*PRW_LOCK;


  142. #ifdef __cplusplus
  143. extern "C"
  144. {
  145. #endif

  146. PVOID __stdcall CreateRWLock();

  147. VOID __stdcall DeleteRWLock(PVOID pRWLock);

  148. VOID __stdcall AcquireShareLock(PVOID pRWLock);

  149. BOOL __stdcall TryAcquireShareLock(PVOID pRWLock);

  150. VOID __stdcall ReleaseShareLock(PVOID pRWLock);

  151. VOID __stdcall AcquireExclusiveLock(PVOID pRWLock);

  152. BOOL __stdcall TryAcquireExclusiveLock(PVOID pRWLock);

  153. VOID __stdcall ReleaseExclusiveLock(PVOID pRWLock);

  154. #ifdef __cplusplus
  155. }
  156. #endif

  157. #endif
复制代码

Rank: 2

发表于 2012-3-9 23:19:48 |显示全部楼层
eaglenet 发表于 2012-3-9 22:31
诸位,我第一次听说“临界体的获取和释放必须在同一个线程”这种事情..诸位大哥,我被这哥们打败了,KiCa ...

在自己看清楚临界体的实质
常识性东西先搞清楚好不好!
MSDN关于这个问题有明确的解释!

Rank: 2

发表于 2012-3-9 23:26:04 |显示全部楼层
eaglenet 发表于 2012-3-9 22:28
哎...我不是反对不要读写锁,而是想告诉你,在用读写锁的时候,要确定是不是锁阻碍了你的并发.如果不是, ...

我说了。。。。。就是每秒可能多达10万以上的读,但是写操作可能几个小时甚至几天都不会有一次
但是,一旦有写,没上锁独占的话,就可能导致与读竞争资源而出问题

Rank: 2

发表于 2012-3-9 23:45:08 |显示全部楼层
http://msdn.microsoft.com/zh-cn/library/ms886733.aspx
搞清楚,
读写锁是线程相关的东西

你没听说的东西还多了去了!!!

Rank: 2

发表于 2012-3-9 23:47:56 |显示全部楼层
If a thread calls LeaveCriticalSection when it does not have ownership of the specified critical section object, an error occurs that may cause another thread using EnterCriticalSection to wait indefinitely.

如果一个线程调用LeaveCriticalSection释放一个不被它占有的临界体,就会出错从而导致。。。。。。。。。。。。。。

Rank: 2

发表于 2012-3-10 08:40:18 |显示全部楼层
Cyg07 发表于 2012-3-9 22:44
不就是想支持大并发么。通过拼命抢夺一个资源的利用来提高并发量是非常有局限的,把读写分开,考虑多空间和 ...

你都没搞明白加锁的目的。
不是我要抢一个资源从而提高并发率。
而是,别人会很大并发的提交数据给我要求我处理(别人提交给我的速度完全不是本机受控的,无法控制)。
而为了处理这个数据,我要用到一个表里的东西。这个表里的内容随时可能被修改,时间不确定;但是修改的次数会很少。。。。。可能几个小时甚至几天一次。这个虽然频率很低,但是一旦要修改,如果没加锁,就可能与仅仅是访问下表里内容的线程冲突。所以实际上,除了有并发读写的时候外,仅仅只有读的时候是不需要加锁的,理论上。

读写锁正是这个目的。你以为是搞100个线程读文件然后提高效率啊!!

Rank: 1

发表于 2012-3-10 09:29:04 |显示全部楼层
谁来搞并发量我不管。但是你想支持高并发,是吧?
你不就是一个资源,可能由于读写操作不同步XXOO了么,是吧?
什么写频率的问题,那也不是由你来决定的,是吧?
你提供这么一个读写锁的解决方案,却说自己支持多高的并发,是吧?
你说你一秒内10W+的读取,在这瞬间你加锁了。我去,多少请求挂住了?
你仔细想想能不能把这个锁去了,让系统来保证你的读写是原子性的?

Rank: 2

发表于 2012-3-10 10:08:39 |显示全部楼层
Cyg07 发表于 2012-3-10 09:29
谁来搞并发量我不管。但是你想支持高并发,是吧?
你不就是一个资源,可能由于读写操作不同步XXOO了么,是 ...

写是可控
而且频率很低

举个例子总共十秒
加起来总共100万个读请求,没有写操作时,可能一共要11秒处理完
在第5秒内,有一个写操作,这时所有的后续读操作在我写锁解除前是卡住的
我的写操作花费0.1毫秒,可能。。然后写锁被解除。。之前所有pengding的操作继续被处理
这时总共花费11.0001秒

如果用普通锁。。。。那这100万个读请求+一个写请求,就必须是,
处理第一个请求,后面来的所有请求都卡住
第一个请求处理完,接着处理第二个,第二个后的所有请求都卡住。。。。。。。。你自己算算要多少时间??!!!
你说用系统保证我的所有对表里的访问都是原子的。。。假设不用锁。。。貌似我知道的所谓原子操作就是Interlocked那一套
但是我对数据的处理,并不是简单的对表里的某值加1或者减1或者做个值交换
你找出个更高明点的办法?

Rank: 2

发表于 2012-3-10 10:14:01 |显示全部楼层
Cyg07 发表于 2012-3-10 09:29
谁来搞并发量我不管。但是你想支持高并发,是吧?
你不就是一个资源,可能由于读写操作不同步XXOO了么,是 ...

估计你认为我所谓的读操作
就仅仅是从表里取个数据的值出来
然后这时这个表再怎么变就不管了
事实上是
在我整个操作(包括往返多次读表里的数据,然后对数据进行分,这中间不允许表里的数据有任何变化)中,我必须保证表里面内容固定不变

你想个不用锁的。。。高明点的办法?

Rank: 1

发表于 2012-3-10 11:14:40 |显示全部楼层
我们提的根本不是一回事了,能挂得起来那些请求那就不是提高并发的事了。
如果前端的交互已经可以异步了,那就更没什么好讲了。
每一种方法都有它最大化效益的临界点,不用锁也有不用锁的代价,可能在你需要的时候你自己会碰到。

我们回到帖子上。仔细看了下帖,我也只看后面的数据讨论,重新看了下大鹰跟你说的。哈哈哈,你代码给谁用的?你都没能给出你这个锁用的框架。比如大鹰说的那套是支持一个写,多个读的,你的呢?大鹰给的代码就是个问题了。

Rank: 1

发表于 2012-3-10 11:17:10 |显示全部楼层
没人要求你改,也没人要求你如何?
只是说你的框架是否可以更好的扩展,而你总是想以自我最优来看待大家。

Rank: 1

发表于 2012-3-10 13:36:39 |显示全部楼层
本来只是想给你个建议,让你能够继续优化你的实现,也想着少让你走些弯路。仅此而已.

Rank: 2

发表于 2012-3-10 14:20:22 |显示全部楼层
Cyg07 发表于 2012-3-10 11:14
我们提的根本不是一回事了,能挂得起来那些请求那就不是提高并发的事了。
如果前端的交互已经可以异步了,那 ...

我发的这个就是支持一个写,多个读的啊


不然叫什么读写锁

写不允许重入。。。。读允许重入
读写不允许同时存在

这不就是读写锁的基本要求么。。。。。
您需要登录后才可以回帖 登录 | 立即加入

Archiver|手机版|第8个男人 - 论坛为只读模式,仅供查阅

GMT+8, 2019-1-22 10:31 , Processed in 0.032919 second(s), 7 queries .

Design by pvo.cn

© 2011 Pvo Inc.

回顶部