zoukankan      html  css  js  c++  java
  • 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}" +
    " SafeCountInstances: {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

  • 相关阅读:
    更改sql server数据库所有者的对象
    对C#委托及事件委托的理解
    印度人是怎样开发软件的?
    SQL常用函数
    Ajax学习1
    Ajax学习2
    什么是ORM?
    jQuery 移动网页到制定的位置
    Juery 控件的取值赋值
    js禁用滚动条
  • 原文地址:https://www.cnblogs.com/fengye87626/p/3831579.html
Copyright © 2011-2022 走看看