zoukankan      html  css  js  c++  java
  • C#线程安全使用(三)

    在讲CancellationTokenSource之前我决定先讲一下lock和Interlocked,如果能很好的理解这两个,再去理解CancellationTokenSource就会方便很多,由于我也是后起使用多线程,使用的时候就是直接运用FramWork4的东西,这样导致了很多东西学起来很吃力,当回顾了以前的知识点后,发现新出的东西如此好理解。

    先看一下Lock的使用,下面是一个例子。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace LockConsole
    {
        class Program
        {
            static object lockint = 0;
            static void Main()
            {
                Task[] tlist=new  Task[10];
    
                Thread[] threads = new Thread[10];
              
                for (int i = 0; i < 10; i++)
                {
                 var action =   new Action<object>(Withdraw);
                 Task t = new Task(action, i);
                 tlist[i] = t;
                    //Thread t = new Thread(new ThreadStart(acc.DoTransactions));
                    //threads[i] = t;
                }
                for (int i = 0; i < 10; i++)
                {
                    tlist[i].Start();
               
                    //threads[i].Start();
                }
                Console.Read();
            }
    
    
            static void Withdraw(object i)
            {
                int amount = int.Parse(i.ToString());
                int  balance = 1000;
    
                lock (lockint)//删除lock就会造成 线程混乱
                {
                    if (balance >= amount)
                    {
                        Console.WriteLine("当前线程{0},当前状态{1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.ThreadState + "Balance before Withdrawal :  " + balance); 
                        Console.WriteLine("当前线程{0},当前状态{1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.ThreadState + "Amount to Withdraw        : -" + amount);
                        balance = balance - amount;
                        Console.WriteLine("当前线程{0},当前状态{1}", Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.ThreadState + "Balance after Withdrawal  :  " + balance);
                       
                    }
                  
                }
            }
    
          
           
        }
       
        
    }
    View Code

    输出结果如下,他的线程都是一个接一个的,线程11后是线程12,然后是13,14,11等。每个线程都是等到执行完了下一个才执行。

     

    在看一下没有Lock的结果,如下图,线程是混乱的,12线程的函数没执行完13就开始了。

    有了上面的例子,Lock就很好理解了,他是为了保障资源同一时间只被一个线程使用,虽然该例子中没有使用Lock的资源,但线程还是一个接一个的执行,因为使用了lock线程就会一个接一个执行。

    接下来看一下interLock,这是一个MSDN的例子,我觉得不错,他的意思是,把usingResource作为一个锁,当多线程开始运行,函数UseResource()需要判断usingResource的值,当usingResource等于0的时候,当前线程不运行,否则运行,当本线程运行时,要修改usingResource的值为1,这样确保其他线程不运行,即同一时间只运行一个线程。

    如果这样需求用到开发中,会出现一个问题,那就是当一个线程改变usingResource的值的一瞬间,别的线程读取了usingResource的值,那这个线程也被运行了。

    这时就需要InterLock了。代码如下。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace MyInterlockedExchangeExampleClass
    {
        class MyInterlockedExchangeExampleClass
        {
            //0 for false, 1 for true.
            private static int usingResource = 0;
    
            private const int numThreadIterations = 5;
            private const int numThreads = 10;
    
            static void Main()
            {
                Thread myThread;
                Random rnd = new Random();
    
                for (int i = 0; i < numThreads; i++)
                {
                    myThread = new Thread(new ThreadStart(MyThreadProc));
                    myThread.Name = String.Format("Thread{0}", i + 1);
    
                    //Wait a random amount of time before starting next thread.
                    Thread.Sleep(rnd.Next(0, 1000));
                    myThread.Start();
                }
            }
    
            private static void MyThreadProc()
            {
                for (int i = 0; i < numThreadIterations; i++)
                {
                    UseResource();
    
                    //Wait 1 second before next attempt.
                    Thread.Sleep(1000);
                }
            }
    
            //A simple method that denies reentrancy.
            static bool UseResource()
            {
                //0 indicates that the method is not in use.
                //原始值是0,判断是时候使用原始值,但判断后值为1,进行了设置
                if (0 == Interlocked.Exchange(ref usingResource, 1))
                {
                    Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name);
    
                    //Code to access a resource that is not thread safe would go here.
    
                    //Simulate some work
                    Thread.Sleep(500);
    
                    Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name);
    
                    //Release the lock
                    Interlocked.Exchange(ref usingResource, 0);
                    return true;
                }
                else
                {
                    Console.WriteLine("   {0} was denied the lock", Thread.CurrentThread.Name);
                    return false;
                }
            }
    
        }
    
    }
    View Code

    理解了lock和interlock后下一章讲解CancellationTokenSource。

    ----------------------------------------------------------------------------------------------------

    注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
    若您觉得这篇文章还不错,请点击下方的推荐】,非常感谢!

     

  • 相关阅读:
    使用springamqp发送消息及同步接收消息
    对未登陆的用户进行处理的页面
    查找某些字符是否在另一个字符串里出现的高效算法
    正则表达式
    华中地区高校第七届ACM程序设计大赛——递增序列【2012年5月27日】
    HDOJ2021 ( 发工资咯:) ) 【水题】
    循环冗余校验(CRC)【C语言 位运算】
    HDOJ2028 ( Lowest Common Multiple Plus ) 【水题,lcm】
    HDOJ2015 ( 偶数求和 ) 【水题】
    HDOJ2027 ( 统计元音 ) 【水题】
  • 原文地址:https://www.cnblogs.com/kiba/p/3380712.html
Copyright © 2011-2022 走看看