首页 新闻 会员 周边

c#多线程lock问题

0
悬赏园豆:5 [已解决问题] 解决于 2013-08-05 15:30

下面是我从百度文库里看到的一段:

 

下面是一个使用lock关键字的典型例子,我将在注释里向大家说明lock关键字的用法和用途:  //lock.cs 
  using System; 
  using System.Threading;   
  internal class Account    { 
    int balance; 
    Random r = new Random();     internal Account(int initial)      { 
      balance = initial;     }   

 

 


    internal int Withdraw(int amount)      { 
      if (balance < 0)        { 
        file://如果balance小于0则抛出异常         throw new Exception("Negative Balance");       } 
      //下面的代码保证在当前线程修改balance的值完成之前       //不会有其他线程也执行这段代码来修改balance的值       //因此,balance的值是不可能小于0的       

    lock (this)       { 
        Console.WriteLine("Current Thread:"+Thread.CurrentThread.Name);         

file://如果没有lock关键字的保护,那么可能在执行完if的条件判断之后         

file://另外一个线程却执行了balance=balance-amount修改了balance的值         

file://而这个修改对这个线程是不可见的,所以可能导致这时if的条件已经不成立了 

file://但是,这个线程却继续执行balance=balance-amount,所以导致balance可能小于0 
        if (balance >= amount)          { 
          Thread.Sleep(5); 
          balance = balance - amount;           return amount; 

    ...(http://wenku.baidu.com/view/9510d2649b6648d7c1c746c5.html

 

我想知道的是即使这一小段代码即使加了lock,不还是可能在执行完if的条件判断之后,另外一个线程却执行了balance=balance-amount修改了balance的值。这个lock是不是应该放在判断balance之前?

While蹒跚学步...的主页 While蹒跚学步... | 初学一级 | 园豆:59
提问于:2013-08-05 14:58
< >
分享
最佳答案
1

1,balance 是允许被多次修改的,所以,另一个线程执行了  balance=balance-amount 是逻辑上正确的;

2,lock 是防止脏读,也就是你需要修改的 balance 的值,并不是你上次读取到的 balance 的值。

看这段代码:

lock(this) 所有的调用线程都会阻塞在这里,只有一个线程会被允许进入下面的代码;

if(balance >= amount)

balance = balance - amount;

// 因为前面加了 lock ,所以可以确保判断语句读取到的 balance 的值和修改语句读取到的 balance 的值是一样的,那么这就确保了在共享变量 balance 上的修改操作是原子性的,不会发生数据不一致性。

当前线程执行完后就退出了,那么在 lock(this)上等待的其它线程会有一个被允许进入此段代码,这就是你的疑惑点,但是这是正确的,因为不论从逻辑上还是业务规则上,balance 都是允许被多次修改的,我们这里放置 lock,是为了避免要修改的值并不是我们先前读取到的值的问题。

收获园豆:5
Launcher | 高人七级 |园豆:45045 | 2013-08-05 15:13

我指的是前面 if (balance < 0)这个判断,lock(this) 所有的调用线程都会阻塞在这里,只有一个线程会被允许进入下面的代码;那么当进入的线程改变了balance的值使得它小于0了,所以是不是lock应该放在if (balance < 0)之前? 谢谢

While蹒跚学步... | 园豆:59 (初学一级) | 2013-08-05 15:19

@While蹒跚学步...: 交易判断的依据是 balance >= amount。if(balance < 0) 是永远都不应该发生的情况,所以原文有句注释 “ file://如果balance小于0则抛出异常         throw new Exception("Negative Balance");   ”。

Launcher | 园豆:45045 (高人七级) | 2013-08-05 15:24

@Launcher: 明白了,非常感谢

While蹒跚学步... | 园豆:59 (初学一级) | 2013-08-05 15:29
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册