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获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
随机推荐
- SQL Server批量更新数据
项目中有一个位置需要批量插入几万条数据,批量insert等待时间简直...用SqlBulkCopy后,之前需要1分钟左右的sql现在只要一眨眼(真的只要一眨眼) 稍后这个功能要加到另外一个项目中,另外 ...
- css图片映射
a <div class="imagemap"> <img src="img/map.png" width="496px" ...
- js学习笔记—转载(闭包问题)
---恢复内容开始--- 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascrip ...
- 每天一道LeetCode--118. Pascal's Triangle(杨辉三角)
Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Retur ...
- JDBC之初识
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口 ...
- 使用ptrace向已运行进程中注入.so并执行相关函数
这个总结的很好,从前一个项目也用到这中技术 转自:http://blog.csdn.net/myarrow/article/details/9630377 1. 简介 使用ptrace向已运行进程中注 ...
- popViewControllerAnimated 后,对页面内UITableView 内数据刷新
popViewControllerAnimated后,这时它不执行viewDidLoad,所以不能及时对viewControler及时刷新,此时对该页面进行操作可以调用viewWillAppear:( ...
- ASP.NET实现折线图的绘制
用到.Net中绘图类,实现折线图的绘制,生成图片,在页面的显示,代码如下: /// <summary> /// 获取数据 /// strChartName:图名称: /// yName:纵 ...
- 客户端javascript笔记
html 中的 onclick访问的是全局作用域
- linux 安装mysql后修改密码出现问题
新安装的mysql 执行命令时候出现错误: 一 错误信息: ERROR 1045 (28000): Access denied for user 'mysql'@'localhost' (using ...