返回列表 回复 发帖

WINDOWS下通过事件对象和临界区实现“读写锁”

  1. void rwlock::lock(int _direct)
  2. {
  3.     EnterCriticalSection(&start_lock);
  4.     while (count > 0 && (direct != _direct || _direct == LOCK_WRITE))
  5.     {
  6.         WaitForSingleObject(finish_event, INFINITE);
  7.     }
  8.     direct = _direct;
  9.     InterlockedIncrement(&count);
  10.     LeaveCriticalSection(&start_lock);
  11. }

  12. void rwlock::unlock(int _direct)
  13. {
  14.     InterlockedDecrement(&count);
  15.     SetEvent(finish_event);
  16. }
复制代码
其中direct为当前进行中的读写状态

1、当第一次有READ请求进入的时候,由于count计数为0,将direct标记为READ并增加count计数后就直接跳出锁执行下面的代码。
当前状态:direct==READ,count==1
2、当第二次有WRITE请求进入的时候,由于count计数为1,direct不为READ,条件成立后进入事件等待。
当前状态:direct==READ,count==1
3、当第三次有READ请求进入的时候,由于direct等于READ,所以直接增加count的计数后跳出锁执行下面的代码。
当前状态:direct==READ,count==2
4、当执行一次unlock时,count计数减去1,给EVENT一个信号量,让队列中的某一个线程继续执行,此时count为1并且队列中的请求为WRITE(因为direct为READ,所以所有的READ请求都被放行了),所以继续等待下次EVENT的触发,SetEvent的第二个参数为FALSE,所以信号是自动重置的。
当前状态:direct==READ,count==1
5、当再次执行unlock时,count==0,此时WRITE请求被放行,并将direct设置成WRITE,count为1,然后跳出锁执行写操作。
当前状态:direct==WRITE,count==1
6、 此时如果有READ请求的话,由于count>0,并且direct!=READ,,所以READ请求进入等待队列。
  当前状态:direct==WRITE,count==1
7、 如果有WRITE请求的话,由于count>0,并且_direct==LOCK_WRITE,所以也进入对待队列。
当前状态:direct==WRITE,count==1
读写锁,使用尽量谨慎。这个东西,稍微不留意,就是各种问题。

所以,在一些数据重要的场合,如数据库,锁都是由数据库软件自己管理。用户尽量避免直接用锁。
在网上购买本书的读者,请给本书发一个好评。谢谢大家。
回复 2# fwbook

我是准备把数据读取到内存中建立一个缓存,这样可以减少对数据库的操作。读写锁是用来保护内存中的数据的。
回复 3# ghosthand


    这样不错。可以提升性能。
返回列表