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 方法作用的更多相关文章

  1. 多线程相关Interlocked.Increment问题

    今天群里有人问到如下代码打印出来的东西为什么不是连续得,所以有大神解释了原因.在这过程中遇到了些奇怪的情况 static void Main(string[] args) { for (int i = ...

  2. Interlocked.Increment()函数详解 (转载)

    原文地址 class Program { static object lockObj = new object(); ; ; //假设要处理的数据源 , ).ToList(); static void ...

  3. .Net Core在X86上实现Interlocked.Increment(ref long)的方式

    因为在X86上long会被分割为两个int进行操作, 那么Interlocked.Increment的实现成为了一个问题. 在一番搜索后未发现有现成的文章解释这个问题,于是我就动手分析了. 这篇是笔记 ...

  4. 对象回收过程?线程池执行过程? map原理?集合类关系?synchronized 和 volatile ? 同一个类的方法事务传播控制还有作用吗?java 锁

    1.  对象回收过程? 可达性分析算法: 如果一个对象从 GC Roots 不可达时,则证明此对象不可用. 通过一系列称为GC ROOTS的对象作为起点,从这些起点往下搜索,搜索走过的路径 称为引用链 ...

  5. 方法覆盖 和toString方法的作用

    当我们代码怎么编写的时候,在代码级别上构成了方法的覆盖呢? 两个类必须要有继承关系. 重写之后的方法和之前的方法具有:相同的返回值类型 相同的方法名 相同的形参列表 访问权限不能更高,只能更低 重写之 ...

  6. MVC学习系列4--@helper辅助方法和用户自定义HTML方法

    在HTML Helper,帮助类的帮助下,我们可以动态的创建HTML控件.HTML帮助类是在视图中,用来呈现HTML内容的.HTML帮助类是一个方法,它返回的是string类型的值. HTML帮助类, ...

  7. 基于jquery的has()方法以及与find()方法以及filter()方法的区别详解

    has(selector选择器或DOM元素)   将匹配元素集合根据选择器或DOM元素为条件,检索该条件在每个元素的后代中是否存在,将符合条件的的元素构成新的结果集. 下面举一个例子: <ul& ...

  8. Ajax跨域的几种方法以及每种方法的原理

    js中几种实用的跨域方法原理详解 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协 ...

  9. spring aop获取目标对象的方法对象(包括方法上的注解)

    这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...

随机推荐

  1. 纯CSS手风琴效果

    CSS手风琴效果 主体代码如下:                                                                                     ...

  2. Javascript之改变盒子颜色

    index.html: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...

  3. 关于对XE7中introduced in an ancestor and cannot be deleted的解决方案

    在Delphi XE7中设计Multi-Device Application 类型窗体中,发现删除一个组件时,提示introduced in an ancestor and cannot be del ...

  4. Convert Windows 32bit dirver to Windows 64bit

    Pre-condition: 1.source code(vc6.0+WDK based) Development environment: 2.VS2013 3.WDK 8/8.1 Steps: 1 ...

  5. 第三篇、image 设置圆角的几种方式

    第一种: 就拿view来举例 view.layer.masksToBounds=YES; //设置为yes,就可以使用圆角 view.layer.cornerRadius= ; //设置它的圆角大小 ...

  6. Objective-C调用Swift

    如果已经有了一个老的iOS应用,它是使用Objective-C编写的,而它的一些新功能需要采用Swift来编写,这时就可以从Objective-C调用Swift. Objective-C调用Swift ...

  7. WCF学习笔记 -- 基本概念

    WCF是实现WebService的一种微软提出的技术,整合了.Remote, .NET及ASP.NET服务的一种框架.是Windows Communication Foundation的缩写.WebS ...

  8. C++运用SDK截屏

    引言 最近有一个需要截取当前屏幕,并保存成BMP文件的需求.整个需求,拆分成三步:1.截取屏幕,获得位图数据.2.配合bmp文件结构信息,将数据整合.3.对整合后的数据做操作,如保存在本地.通过网络传 ...

  9. Linux 配置

    零:个性化 主题:Radiance 主题颜色: gtk-color-scheme = "base_color:#CCE8CF\nfg_color:#006400\ntooltip_fg_co ...

  10. log4j配置只打印指定jar或包的DEBUG信息

    有的时候查问题的时候需要打印第三方jar里面的debug信息,假如全部jar都打印的话日志文件会很大,这个时候可以配置log4j只打印指定jar的debug信息或者包,同时输出到了一个新的文件中. 比 ...