C#线程同步技术(二) Interlocked 类
接昨天谈及的线程同步问题,今天介绍一个比较简单的类,Interlocked。它提供了以线程安全的方式递增、递减、交换和读取值的方法。
它的特点是:
1、相对于其他线程同步技术,速度会快很多。
2、只能用于简单的同步问题。
比叫好理解,不再赘述,给一个我们常用的单例模式的 Interlocked 实现:
class SourceManager
{
private SourceManager() { } private static SourceManager sourceManager;
public static SourceManager Instance
{
get
{
if (sourceManager == null)
{
/* lock 实现方式
功能与以下 Interlocked.CompareExchange 相同 lock (this)
{
if (sourceManager == null)
{
sourceManager = new SourceManager();
}
} */
Interlocked.CompareExchange<SourceManager>(ref sourceManager, new SourceManager(), null);
}
return sourceManager;
}
}
}
Interlocked 类用于使变量的简单语句原子化。再用一个例子说明用 Interlocked 实现线程安全资源锁定机制。
在这个例子中,我们会建立10任务,每个任务会分别循环50000次请求使用资源,而这种资源我们限定同一时间只能有一个线程访问,请求成功则递增 accessed 值,失败则递增 denied 值,因此按我们的预期,accessed 和 denied 的和将会始终是 10*50000 = 500000。且看我们设计的机制:
class InterlockedCase
{
private static int accessed = ;
private static int denied = ; // 0 没有线程在使用 1 有线程正在使用
private static int usingResource = ; private const int nTaskIterations = ;
private const int nTasks = ; public static void Test()
{
Task[] tasks = new Task[nTasks];
for (int i = ; i < nTasks; i++)
{
tasks[i] = Task.Factory.StartNew(ThreadProc);
}
for (int i = ; i < nTasks; i++)
{
tasks[i].Wait();
}
Console.WriteLine("accessed:{0}, denied:{1}, total:{2}", accessed, denied, accessed+denied);
} private static void ThreadProc()
{
for (int i = ; i < nTaskIterations; i++)
{
UseResource();
}
} private static bool UseResource()
{
if (usingResource == )
{
usingResource = ; accessed++; usingResource = ;
return true;
}
else
{
Interlocked.Increment(ref denied);
return false;
}
}
}
上面例子的运行结果total值却不是我们预期的总请求数 50000!
在代码中,我们设计了一个访问共享资源的逻辑
if (usingResource == 0)
{
usingResource = 1;
accessed++;
usingResource = 0;
return true;
}
错误的原因是我们控制资源的逻辑里 usingResource 的判断和赋值操作并不是原子操作,会导致有多个线程能同时进入内层操纵资源,修改 accessed!导致 accessed 值的统计不准确!
找到原因,我们把 usingResource 的判断和赋值转为原子操作,就能实现我们的构想了,Interlocked 类正好派上用场!
改造 UseResource() 函数,输出结果正式我们期望的 500000
private static bool UseResource()
{
if (Interlocked.Exchange(ref usingResource,) == )
{
accessed++;
usingResource = ;
return true;
}
else
{
Interlocked.Increment(ref denied);
return false;
}
}
读到这里,有心的朋友可能会问,usingResource 变量为何设计成整型值?用布尔值不好吗?这正是体现整型值的灵活的地方,我们可以通过更改 UseResource() 函数的逻辑,控制统一时间可以有多少个线程访问资源,而并非只限定一个线程可以访问。
后话:
这是第二篇关于线程同步的学习笔记,其实书看得很快,但是文章却写得很慢。我发觉学习线程同步最好的方式就是设计一个反例,并更正它,确认运行结果是否与你预期的一致。在写这篇文章的过程中,我试图设计很多例子,也激发了自己很多的思考,其中有些想法开始是错的,在不断对比思考的过程里,逐渐加深认识了线程资源访问的设计。在大逻辑上,上一篇中 lock 语句会等待资源的释放,直至访问成功完成任务;而本篇中我们的线程会视图访问一些资源,不成功时我们会干别的事情,不会等待。
希望在这一系列文章写完的时候,我会对线程的同步有一个正确且深刻的认识,这也是我写这些读书笔记的目的。
C#线程同步技术(二) Interlocked 类的更多相关文章
- 【WIN32进阶之路】:线程同步技术纲要
前面博客讲了互斥量(MUTEX)和关键段(CRITICAL SECTION)的使用,想来总觉不妥,就如盲人摸象一般,窥其一脚而言象,难免以偏概全,追加一篇博客查遗补漏. win32下的线程同步技术分为 ...
- 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock
[源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...
- 转:C# 线程同步技术 Monitor 和Lock
原文地址:http://www.cnblogs.com/lxblog/archive/2013/03/07/2947182.html 今天我们总结一下 C#线程同步 中的 Monitor 类 和 Lo ...
- iOS开发系列-线程同步技术
概述 多线程的本质就是CPU轮流随机分配给每条线程时间片资源执行任务,看起来多条线程同时执行任务. 多条线程同时访问同一块资源,比如操作同一个对象.统一变量.同一个文件,就会引发数据错乱和数据安全的问 ...
- C#线程同步技术(一) lock 语句
开篇语: 上班以后,烦恼少了,至少是没有什么好烦的了,只要负责好自己的工作就可以了,因此也有更多的时间去探索自己喜欢的程序.买回来的书已经看了一半,DEMO也敲了不少,昨晚终于在这里开BLOG,记录一 ...
- Delphi 线程同步技术(转)
上次跟大家分享了线程的标准代码,其实在线程的使用中最重要的是线程的同步问题,如果你在使用线程后,发现你的界面经常被卡死,或者无法显示出来,显示混乱,你的使用的变量值老是不按预想的变化,结果往往出乎意料 ...
- (删)Java线程同步实现二:Lock锁和Condition
在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...
- java线程池技术(二): 核心ThreadPoolExecutor介绍
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...
- JAVA线程同步 (二)notify()与notifyAll()-***
编写多线程程序需要进行线程协作,前面介绍的利用互斥来防止线程竞速是来解决线程协作的衍生危害的.编写线程协作程序的关键是解决线程之间的协调问题,在这些任务中,某些可以并行执行,但是某些步骤需要所有的任务 ...
随机推荐
- Educational Codeforces Round 9 F. Magic Matrix 最小生成树
F. Magic Matrix 题目连接: http://www.codeforces.com/contest/632/problem/F Description You're given a mat ...
- 使用 Google Code Prettify 实现代码高亮
今天这篇文章主要讲述使用 google-code-prettify 来实现代码的高亮显示,以前我使用 highlight.js 来实现文章中代码的高亮显示. prettify 非常小巧且配置简单,使用 ...
- CentOS 6.9下KVM虚拟机快照创建、删除、恢复(转)
使用文件快照的方式实现文件备份,但单说快照(snapshot)的话,他是某一时间点(版本)你能看到的该时间点备份文件状态的全貌,通过文件的快照(全貌)你能恢复到特定时间点(版本)的文件状态. 创建虚拟 ...
- WPF的UI虚拟化
许多时候,我们的界面上会呈现大量的数据,如包含数千条记录的表格或包含数百张照片的相册.由于呈现UI是一件开销比较大的动作,一次性呈现数百张照片就目前的电脑性能来说是需要占用大量内存和时间的.因此需要对 ...
- winform窗体MaximizeBox
如果MaximizeBox为false会导致Form2窗体底部不显示. =>解决办法TopMost属性为true. Form2 _frm2 = new Form2(); _frm2.Maximi ...
- FTP具有两种模式
FTP具有两种模式,分别是port模式(也叫主动模式)和pasv模式(也叫被动模式),怎么来理解这两种模式呢?我来打个比喻吧,在主动模式下:客户端给服务器端的21端口发命令说,我要下载什么什么,并且还 ...
- 降维工具箱drtool
工具箱下载:http://leelab.googlecode.com/svn/trunk/apps/drtoolbox/ ——————————————————————————————————————— ...
- 央行mlf,SLF,PSL,MLF,SLO
央行mlf是什么意思 中国人民银行 中国人民银行(The People's Bank Of China,英文简称PBOC),简称央行,是中华人民共和国的中央银行,中华人民共和国国务院组成部门.在国务院 ...
- [转]SSIS error DTS_E_CANNOTACQUIRECONNECTIONFROMCONNECTIONMANAGER when connecting to Oracle data source
本文转自:http://blogs.msdn.com/b/jorgepc/archive/2008/02/12/ssis-error-dts-e-cannotacquireconnectionfrom ...
- Solr 中 Schema 结构说明
schema.xml位于solr/conf/目录下,类似于数据表配置文件,定义了加入索引的数据的数据类型,主要包括type.fields和其他的一些缺省设置 1.schema的基本配置 <?xm ...