Interlocked.Increment 方法 和Interlocked.Decrement 方法作用
Interlocked.Increment 方法:让++成为原子操作;Interlocked.Decrement 方法让--成为原子操作。
什么叫原子操作呢。就是不会被别人打断,因为C#中的一个语句,编译成机器代码后会变成多个语句。
在多线程环境中,线程切换有可能会发生在这多个语句中间。使用Interlocked.Increment,Interlocked.Decrement 可以避免被打断,保证线程安全。
使用Interlocked.Increment 方法和Interlocked.Decrement 方法MSND例子:
using System;
using System.Threading;
class Test
{
static void Main()
{
Thread thread1 = new Thread(new ThreadStart(ThreadMethod));
Thread thread2 = new Thread(new ThreadStart(ThreadMethod));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
// Have the garbage collector run the finalizer for each
// instance of CountClass and wait for it to finish.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("UnsafeInstanceCount: {0}" +
"\nSafeCountInstances: {1}",
CountClass.UnsafeInstanceCount.ToString(),
CountClass.SafeInstanceCount.ToString());
}
static void ThreadMethod()
{
CountClass cClass;
// Create 100,000 instances of CountClass.
for(int i = 0; i < 100000; i++)
{
cClass = new CountClass();
}
}
}
class CountClass
{
static int unsafeInstanceCount = 0;//不使用原子操作
static int safeInstanceCount = 0;//使用原子操作
static public int UnsafeInstanceCount
{
get {return unsafeInstanceCount;}
}
static public int SafeInstanceCount
{
get {return safeInstanceCount;}
}
public CountClass()
{
unsafeInstanceCount++;
Interlocked.Increment(ref safeInstanceCount);
}
~CountClass()
{
unsafeInstanceCount--;
Interlocked.Decrement(ref safeInstanceCount);
}
}
不用原子操作例子
class Program
{
static void Main(string[] args)
{
for (int loop = 0; loop < 20; loop++)
{
sum = 0;
Thread t1 = new Thread(Thread1);
Thread t2 = new Thread(Thread2);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine("sum = " + sum); // sum = 200000 ?
}
}
static int sum;
static void Thread1()
{
for (int i = 0; i < 100000; i++) sum++;
}
static void Thread2()
{
for (int i = 0; i < 100000; i++) sum++;
}
}
结果:
/*
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 192361
sum = 175155
sum = 200000
sum = 176024
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 200000
sum = 176322
*/
Why the sum is not always 200000?
The reason is that sum++ is not thread safe (see the possible problem).
That is the reason we need Interlocked.Increment(), which guarantees the sum is always 200000.
Thread1 (sum++) Thread2 (sum++)
--------------------------------------------------------------------
mov EAX, dword ptr sum .
inc EAX .
. mov EAX, dword ptr sum // load sum into a register
. inc EAX // increase it
. mov dword ptr sum, EAX // save back
mov dword ptr sum, EAX
--------------------------------------------------------------------
problem: two sum++ are called in different thread,
but the sum is incremented only once.
也就是说因为C#中的一个语句,编译成机器代码后会变成多个语句,线程不安全,sum++的第100次操作就被打断了,而在第200000次++操作结束后CPU才轮询到sum++的第100次操作,这时sum的值就是101,
转自: http://www.cnblogs.com/cappuccino/archive/2011/01/06/1927659.html
Interlocked.Increment 方法 和Interlocked.Decrement 方法作用的更多相关文章
- 多线程相关Interlocked.Increment问题
今天群里有人问到如下代码打印出来的东西为什么不是连续得,所以有大神解释了原因.在这过程中遇到了些奇怪的情况 static void Main(string[] args) { for (int i = ...
- Interlocked.Increment()函数详解 (转载)
原文地址 class Program { static object lockObj = new object(); ; ; //假设要处理的数据源 , ).ToList(); static void ...
- .Net Core在X86上实现Interlocked.Increment(ref long)的方式
因为在X86上long会被分割为两个int进行操作, 那么Interlocked.Increment的实现成为了一个问题. 在一番搜索后未发现有现成的文章解释这个问题,于是我就动手分析了. 这篇是笔记 ...
- 对象回收过程?线程池执行过程? map原理?集合类关系?synchronized 和 volatile ? 同一个类的方法事务传播控制还有作用吗?java 锁
1. 对象回收过程? 可达性分析算法: 如果一个对象从 GC Roots 不可达时,则证明此对象不可用. 通过一系列称为GC ROOTS的对象作为起点,从这些起点往下搜索,搜索走过的路径 称为引用链 ...
- 方法覆盖 和toString方法的作用
当我们代码怎么编写的时候,在代码级别上构成了方法的覆盖呢? 两个类必须要有继承关系. 重写之后的方法和之前的方法具有:相同的返回值类型 相同的方法名 相同的形参列表 访问权限不能更高,只能更低 重写之 ...
- MVC学习系列4--@helper辅助方法和用户自定义HTML方法
在HTML Helper,帮助类的帮助下,我们可以动态的创建HTML控件.HTML帮助类是在视图中,用来呈现HTML内容的.HTML帮助类是一个方法,它返回的是string类型的值. HTML帮助类, ...
- 基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
has(selector选择器或DOM元素) 将匹配元素集合根据选择器或DOM元素为条件,检索该条件在每个元素的后代中是否存在,将符合条件的的元素构成新的结果集. 下面举一个例子: <ul& ...
- Ajax跨域的几种方法以及每种方法的原理
js中几种实用的跨域方法原理详解 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协 ...
- spring aop获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
随机推荐
- .NET 认识
- Category
Category 首先我们来谈谈Category. Objective-C提供了一种与众不同的方式——Catagory,可以动态的为已经存在的类添加新的行为.这样可以保证类的原始设计规模较小,功能增加 ...
- Asp.Net运行原理(=)
浏览器与服务器之间的通信. 一般浏览器与服务器之间的底层是通过socket建立连接的. 当浏览器与服务器之间建立了socket连接之后,服务器就开始监听. 当浏览器与服务器之间建立了相互兼容的协议之后 ...
- JqGrid 使用方法详解
JQGrid JQGrid是一个在jquery基础上做的一个表格控件,以ajax的方式和服务器端通信. JQGrid Demo 是一个在线的演示项目.在这里,可以知道jqgrid可以做什么事情. 下面 ...
- jQuery实现CheckBox全选、全不选
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- XPOSED-LUA
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/xposed-lua/ 说明 Xposed Lua Module 是一个Xposed的模块,他有下面的优点 本 ...
- xamarin.ios 豆瓣电台视频教程
视频中提到的网址: http://www.sufeinet.com/thread-655-1-1.html https://github.com/akfish/fm-terminal/blob/dev ...
- httpd 配置用户访问认证
需求:单用户访问网站的某个目录,需要使用帐号密码来登录才能访问. 一.编辑虚拟主机的配置文件,添加目录级访问限制 <Directory "/var/www/html/demo" ...
- OpenCV3添加滑动条和鼠标事件到图形界面
鼠标事件和滑动条控制在计算机视觉和OpenCV中非常有用,使用这些控件,用户可以直接与图形界面交互,改变输入图像或者变量的属性值. /* In this section, we are going t ...
- java实现多模匹配算法
这个是好几年前写的了.都统一放到cnblogs上面. --------------------------------Node ---------------------------------- p ...