当前位置:编程学习 > asp >>

ASP.NET温故而知新学习系列之ASP.NET多线程编程—.NET下的多线程编程临界区(八)

阅读目录
  一:临界区概述
  二:临界区操作
  三:实例
  四:通过Interlocked类设置临界区
  五:通过Monitor类设置临界区
  一:临界区概述
  在某个时间段内可以有两个线程同时执行,那么两个线程访问的要都是同一个数据的话,那么这种情况下会出现一些不必要的事情,比如:我的银行账户总额有5000,某天我拿着存折去柜台取4000准备交物业费,媳妇拿着银行卡去取2000给孩子交学费,当某一个时间点上,我俩同时取钱,那么首先银行是这样操作的,先判断账户余额大于我要取的4000,好了给我吐出来4000大洋,因为是同时进行,媳妇那边也是先判断账户余额大于她要取的2000,好了给她吐出来2000大洋,这样的话我们账户总额只有5000元,我和我老婆却一共取出来了6000元,那么多吐出来的这1000银行只能认了,银行的账户余额为-1000,我们是不希望这种情况发生的,那么我们应该怎么做呢?应该是这样来操作的,首先当我取4000的时候,被锁住也就是我们经常说的加锁,同一个时间点上媳妇取2000的时候,取不了,等我取完了,锁被释放了,媳妇才能取,媳妇取2000的时候系统会提示余额剩下1000了,不能提取2000,那么这里临界区指的就是操作这个数据的区域
  二:临界区操作
  . Lock关键字将某个语句块标记为临界区,另一个线程不能进入临界区
  . Interlocked类为多个线程共享的变量提供原子操作
  . Monitor类提供同步对对象的访问机制,Monitor类通过向单个对象设置对象锁来控制对对象的访问,使用Enter和Exit来标记临界区的开头和结尾
  三:实例
  当我们取消Lock关键字的时候,报异常了如图一,是因为 _money为负数了,也就是账户现有金额为负数了,银行的钱为负数了,我们不取消Lock关键字如图二程序运行正常,为什么会这样呢?红色代码和黄色代码部分为原子操作,当有线程在访问红色代码部分的时候,因为是并行执行,另外的线程也进来了减钱了,如果没有lock关键字的存在,那么两个线程都能执行到黄色代码部分,比如说this._money被减少到等于500的时候,因为intAmount一直都是500,那么if(this._money >= intAmount)是成立的,那么这两个线程都能进到if的语句块里面做黄色代码部分了也就是this._money = this._money - intAmount,第一个线程0=500-500,第二个线程-500=0-500,连着减两次,所以最后this._money为负数了,所以我们要加lock关键字在一个时间点上只能一个线程进来
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading;
  namespace CriticalZone
  {
      public class Money
      {
          public int _money;//账户现有金额
       
          /// <summary>
          /// 初始化账户总额www.zzzyk.com
          /// </summary>
          /// <param name="intTotalMoney">账户总额</param>
          public Money(int intTotalMoney)
          {
              this._money = intTotalMoney;
          }
          /// <summary>
          /// 判断银行剩下的钱是不是负数,如果是负数则抛出异常,如果不是负数则继续取钱
          /// </summary>
          /// <param name="intAmount">要取走的金额</param>
          /// <returns></returns>
          public int Withdraw(int intAmount)
          {
              if (this._money < 0)
              {
                  throw new Exception("银行的钱为负数了");
              }
              return UseLock(intAmount);
          }
          public int UseLock(int intAmount)
          {
      //可以注释lock看看效果
              lock (this)
              {
                  //如果银行的钱大于等于要取走的金额,则减少钱
                  if (this._money >= intAmount)
                  {
                      Thread.Sleep(5);
                      this._money = this._money - intAmount;
                      return intAmount;
                  }
                  else
                  {
                      return 0;
                  }
              }
          }
          /// <summary>
          /// 取钱动作
          /// </summary>
          public void GetMoney()
          {
              //连着取100次500元现金,那么就目前来说,账户总额为5000元,只能取十次就不能取了,账户为0了,金额就不应该在减少了
              for (int  i = 0; i < 100; i++)
              {
                  Withdraw(500);
              }
          }
      }
      class Program
      {
          //声明十个线程,相当于十个人同时去取钱
          static Thread[] threads = new Thread[10];
          static void Main(string[] args)
          {
              Money money = new Money(5000);
              //创建十个线程,这十个线程做同样一件事情GetMoney取钱
              for(int i = 0;i < 10;i++)
              {
    

补充:Web开发 , ASP.Net ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,