技术笔记: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;
读写锁是在进行写数据前先释放掉读锁,然后马上加上写锁,这样后续读缓存的线程就可以继续执行,不会等待。而同时写缓存已经上锁,这样就不会资源冲突。
读写锁这样就可以大大提升读缓存的性能,也不会影响到缓存的更新了。
技术笔记:Delphi多线程应用读写锁的更多相关文章
- Java多线程之读写锁机制
Java多线程中有很多的锁机制,他们都有各自的应用场景,例如今天我说的这种锁机制:读写锁 读写锁,见名知意,主要可以进行两种操作,读和写操作,他们之间结合使用起来又是各不相同的.比如多个线程之间可以同 ...
- java多线程 -- ReadWriteLock 读写锁
写一条线程,读多条线程能够提升效率. 写写/读写 需要“互斥”;读读 不需要互斥. ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作.只要没有 writer,读取锁 ...
- java 多线程 day12 读写锁
import java.util.Random;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent. ...
- 用读写锁三句代码解决多线程并发写入文件 z
C#使用读写锁三句代码简单解决多线程并发写入文件时提示“文件正在由另一进程使用,因此该进程无法访问此文件”的问题 在开发程序的过程中,难免少不了写入错误日志这个关键功能.实现这个功能,可以选择使用第三 ...
- C#使用读写锁三行代码简单解决多线程并发写入文件时线程同步的问题
(补充:初始化FileStream时使用包含文件共享属性(System.IO.FileShare)的构造函数比使用自定义线程锁更为安全和高效,更多内容可点击参阅) 在开发程序的过程中,难免少不了写入错 ...
- C# 防止同时调用=========使用读写锁三行代码简单解决多线程并发的问题
http://www.jb51.net/article/99718.htm 本文主要介绍了C#使用读写锁三行代码简单解决多线程并发写入文件时提示"文件正在由另一进程使用,因此该进程无 ...
- C#使用读写锁解决多线程并发写入文件时线程同步的问题
读写锁是以 ReaderWriterLockSlim 对象作为锁管理资源的,不同的 ReaderWriterLockSlim 对象中锁定同一个文件也会被视为不同的锁进行管理,这种差异可能会再次导致文件 ...
- c++ 读写锁
#ifndef THREAD_UTIL_H #define THREAD_UTIL_H #include <pthread.h> namespace spider { class Auto ...
- Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁
相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...
随机推荐
- 阿里巴巴直播内容风险防控中的AI力量
直播作为近来新兴的互动形态和今年阿里巴巴双十一的一大亮点,其内容风险监控是一个全新的课题,技术的挑战非常大,管控难点主要包括业界缺乏成熟方案和标准.主播行为.直播内容不可控.峰值期间数千路高并发处理. ...
- jQuery的61种选择器
The Write Less , Do More ! jQuery选择器 1. #id : 根据给定的ID匹配一个元素 <p id="myId">这是第一个p标签< ...
- Windows 7上执行Cake 报错原因是Powershell 版本问题
在Windows 7 SP1 电脑上执行Cake的的例子 http://cakebuild.net/docs/tutorials/getting-started ,运行./Build.ps1 报下面的 ...
- Linux CentOS 配置JDK环境
一.下载JDK 下载JDK的方式有两种: 1.Linux中使用wget下载 1.使用命令安装wget yum install wget 2.下载 wget 'http://download.oracl ...
- clr 元数据
clr相关编译器编译生成的托管模块由四部分组成:PE32或32+头.clr头.元数据.IL代码. 元数据和IL代码完全对应,保持一致(:>)性. 元数据有很多用途: VS的智能感知,自动补全: ...
- 从零开始编写自己的C#框架(27)——什么是开发框架
前言 做为一个程序员,在开发的过程中会发现,有框架同无框架,做起事来是完全不同的概念,关系到开发的效率.程序的健壮.性能.团队协作.后续功能维护.扩展......等方方面面的事情.很多朋友在学习搭建自 ...
- 用游标实现查询当前服务器所有数据库所有表的SQL
declare @name varchar(100) DECLARE My_Cursor CURSOR --定义游标 FOR (SELECT Name FROM Master..SysDatabase ...
- 微信小程序监控 - HotApp统计
HotApp小程序统计,第一个专业的微信第三方小程序监控统计工具 1.什么是HotApp小程序统计 HotApp小程序统计是第一个微信第三方小程序统计工具,就像做android 和 ios开发的人知道 ...
- 自建git node pm2 (不赘述,就说遇见的问题)
//======================[git]部分 主题部分还是按照网上的办法进行安装. 安装的话 分为两个办法(一个是yum (contos办法) 或者sudo(ubuntu办法) ...
- (转)从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)
原文地址: http://www.cnblogs.com/lyhabc/p/4682028.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第二篇,主要讲述如何搭建故障转移集 ...