zoukankan      html  css  js  c++  java
  • 技术笔记:Delphi多线程应用读写锁

    在多线程应用中锁是一个很简单又很复杂的技术,之所以要用到锁是因为在多进程/线程环境下,一段代码可能会被同时访问到,如果这段代码涉及到了共享资源(数据)就需要保证数据的正确性。也就是所谓的线程安全。之前写过一篇着于Java线程安全的博客:链接

    我是在写一个服务端程序时应用到读写锁,在一个内存缓存。先来看看排斥锁的写法,代码如下:

    function TValueCalc.GetValue(const key: string): TCache;
    var
      objCache: TCache;
    begin
      Result := nil;  
      //加锁
      FRead2Lock.Enter;
      try
        objCache := GetCacheInstance.GetCache(sKey);
        if objCache <> nil then
        begin
          //缓存正在更新,直接退出,不让线程等待,以提高性能
          if objCache.IsUpdating then
            Exit;
          //是否过期,未过期直接返回
          if MilliSecondsBetween(Now, objCache.LastTime) < Expires then
          begin
            Result := objCache;
            Exit;
          end;
          
          objCache.IsUpdating := True;
        end;
        //更新缓存
        Result := UpdateCache(key);
      finally
        //释放锁
        FRead2Lock.Leave;
      end;
    end;

    但是这个缓存有一个特点,就是每个缓存项存活的时间很短,这就会导致大量的缓存更新操作,而这些更新操作由于业务不同耗时也不同。这就导致线程都在等待缓存的更新。为了解决这个问题引入了读写锁。让读锁可以在写数据时释放,让后面的线程继续执行查找缓存数据。

    function TValueCalc.GetValue(const key: string): TCache;
    var
      objCache: TCache;
    begin
      Result := nil;      
      FRead2Lock.Enter;
      try
        objCache := GetCacheInstance.GetCache(sKey);
        if objCache <> nil then
        begin
          //缓存正在更新,直接退出,不让线程等待,以提高性能
          if objCache.IsUpdating then
            Exit;
          //检查缓存是否过期
          if MilliSecondsBetween(Now, objCache.LastTime) < Expires then
          begin
            Result := objCache;
            Exit;
          end;
          
          objCache.IsUpdating := True;
        end;
        
        //先释放读锁,后面线程可以继续读数据
        FRead2Lock.Leave;
        //加写锁
        FWriteLock.Enter;
        try
          //更新缓存
          Result := UpdateCache(key);
        finally
          //数据更新完毕,重新加上读锁
          FRead2Lock.Enter;
          //释放写锁
          FWriteLock.Leave;
        end;
      finally
        //释放读锁
        FRead2Lock.Leave;
      end;
    end;

    读写锁是在进行写数据前先释放掉读锁,然后马上加上写锁,这样后续读缓存的线程就可以继续执行,不会等待。而同时写缓存已经上锁,这样就不会资源冲突。

    读写锁这样就可以大大提升读缓存的性能,也不会影响到缓存的更新了。

  • 相关阅读:
    learnyou 相关网站
    hdu 3038 How Many Answers Are Wrong
    hdu 3047 Zjnu Stadium 并查集高级应用
    poj 1703 Find them, Catch them
    poj 1182 食物链 (带关系的并查集)
    hdu 1233 还是畅通工程
    hdu 1325 Is It A Tree?
    hdu 1856 More is better
    hdu 1272 小希的迷宫
    POJ – 2524 Ubiquitous Religions
  • 原文地址:https://www.cnblogs.com/5207/p/5133064.html
Copyright © 2011-2022 走看看