gongxp123456
驱动牛犊
驱动牛犊
  • 注册日期2004-12-15
  • 最后登录2013-10-10
  • 粉丝0
  • 关注0
  • 积分617分
  • 威望383点
  • 贡献值1点
  • 好评度59点
  • 原创分0分
  • 专家分0分
阅读:4436回复:8

多线程情况下链表查询是不是必须加锁?

楼主#
更多 发布于:2009-07-12 15:35
《寒江独钓》第244页中的代码注释中,提到,链表的查询的函数应当加锁,从实现的例子的源代码来看,链表的增加删除都加了锁(自己实现,未采用系统提供的加锁版“原生”函数),但是,独有链表的查询未加锁,但是,书中有提到,应当加锁。我理解,多线程链表查询应当可以同时,不加锁也可以。

讨论的问题是:多线程情况下链表查询是不是必须加锁?
jscool520
驱动牛犊
驱动牛犊
  • 注册日期2009-03-13
  • 最后登录2012-12-20
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望101点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-07-13 14:44
查询应该不用加锁,但如果有插入和删除操作就要加锁吧,没有研究过,不知这样理解对不对
jyzhaiyf
驱动牛犊
驱动牛犊
  • 注册日期2004-04-16
  • 最后登录2010-10-02
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望115点
  • 贡献值0点
  • 好评度12点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2009-07-13 14:57
你查询的同时有可能会有对链表删除添加的操作就应加锁。
michaelgz
论坛版主
论坛版主
  • 注册日期2005-01-26
  • 最后登录2012-10-22
  • 粉丝1
  • 关注1
  • 积分150分
  • 威望1524点
  • 贡献值1点
  • 好评度213点
  • 原创分0分
  • 专家分2分
地板#
发布于:2009-07-13 22:19
For synchronization, generally there are two types of locks, READ and WRITE locks. READ lock should be locked for 查询 to prevent 链表 to be changed. WRITE lock should be locked for 增加删除 to prevent any other operations on this 链表.
gongxp123456
驱动牛犊
驱动牛犊
  • 注册日期2004-12-15
  • 最后登录2013-10-10
  • 粉丝0
  • 关注0
  • 积分617分
  • 威望383点
  • 贡献值1点
  • 好评度59点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2009-07-15 09:24
michaelgz说的明白:有两种锁:读锁和写锁,读锁锁的查询操作,写锁锁定增加和删除。

我写了邮件给作者谭文,他很快回信如下:
因为您无法保证在查询过程中,链表被改动(比如在遍历过程中,刚好某个正在遍历的节点被删除)。
实例是很仓促写就的代码,只保证“基本可用”,但并不保证商用级可靠性。所以不加锁并不代表不需要加锁。

结论是:多线程读链表也要加锁!
gongxp123456
驱动牛犊
驱动牛犊
  • 注册日期2004-12-15
  • 最后登录2013-10-10
  • 粉丝0
  • 关注0
  • 积分617分
  • 威望383点
  • 贡献值1点
  • 好评度59点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2009-07-15 09:26
请教michaelgz,锁应当都是一样的吧,怎么有读锁和写锁? (READ and WRITE locks)
gongxp123456
驱动牛犊
驱动牛犊
  • 注册日期2004-12-15
  • 最后登录2013-10-10
  • 粉丝0
  • 关注0
  • 积分617分
  • 威望383点
  • 贡献值1点
  • 好评度59点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2009-07-17 10:56
在多线程的情况下,如果链表都是读是没有问题的,担心读的时候会有写,所以读也采用自旋锁锁定才保险。写是极少,而读是的海量(文件过滤中,每个文件对照一遍),读也搞成单线程,效率影响就太大了,
michaelgz说:有两种锁:读锁和写锁,读锁锁的查询操作,写锁锁定增加和删除:


请教如何实现?多谢!!!
XiangXiangRen
总版主
总版主
  • 注册日期2003-02-22
  • 最后登录2015-09-01
  • 粉丝13
  • 关注0
  • 积分1042分
  • 威望472点
  • 贡献值1点
  • 好评度145点
  • 原创分13分
  • 专家分1分
7楼#
发布于:2009-07-17 15:59
读写锁是可以基于基本的自旋锁来实现的。
概念可以百度一下:http://baike.baidu.com/view/2214179.htm
实现方法在很多教科书上有。
实际上系统中对文件的查询远没有达到需要用读写锁来提高并发性的程度,并没有那么频繁。
所以一般而言简单的使用自旋锁就可以了。
gongxp123456
驱动牛犊
驱动牛犊
  • 注册日期2004-12-15
  • 最后登录2013-10-10
  • 粉丝0
  • 关注0
  • 积分617分
  • 威望383点
  • 贡献值1点
  • 好评度59点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2009-07-17 18:02
多谢XiangXiangRen的指教,谭文也回复了:
“读写锁的实现在许多基础教科书中有讲述。恕我我不能在这里照本宣科。请自己查阅相关书籍...”
当然,加锁是简单的,比如《寒江独钓》第244页的代码:加锁成为:

// 任意给定一个文件,判断是否在加密链表中。这个函数没加锁。
 BOOLEAN cfIsFileCrypting(PFILE_OBJECT file)
{
    PLIST_ENTRY p;
    PCF_NODE node;

KeAcquireSpinLock(&gxp_Lock,&irql);//加锁
for(p = s_cf_list.Flink; p != &s_cf_list; p = p->Flink)
    {
     node = (PCF_NODE)p;
        if(node->fcb == file->FsContext)
        {
            //KdPrint(("cfIsFileCrypting: file %wZ is crypting. fcb = %x \r\n",&file->FileName,file->FsContext));
            KeReleaseSpinLock(&gxp_Lock,irql);//释放锁
           return TRUE;
        }
    }
   KeReleaseSpinLock(&gxp_Lock,irql);//释放锁
   return FALSE;
}

XiangXiangRen认为,对效率影响不大,那就好。
游客

返回顶部