关于lock的一些疑问

小Fan 2011-04-24 03:53:07
以下是MSDN文档里面的代码,
说用了lock锁住了,balance永远不会小于0,为什么呢?
意思是不是说,只执行lock大括号里面的代码,那个 if (balance < 0)就不执行了?

请知道的人解释清楚一下,非常感谢
using System;
using System.Threading;
class Account
{
private object thisLock = new object();
int balance;
Random r = new Random();
public Account(int initial)
{
balance = initial;
}
int Withdraw(int amount)
{
if (balance < 0)
{
throw new Exception("Negative Balance");
}
// Comment out the next line to see the effect of leaving out
// the lock keyword:
lock (thisLock)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdraw1: " + balance);
Console.WriteLine("Amount to Withdraw : " + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0;
}
}
}
public void DoTransactions()
{
for (int i = 0; i < 100; i++)
Withdraw(r.Next(1,100));
}
}
class Text
{
static void Main()
{
Thread[] threads = new Thread[10];
Account acc = new Account(100);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}//此处用2个循环,我把 threads[i].Start();放在第一个循环里面,运行结果也一样,我觉得好像没多大区别
Console.Read();

}
}
...全文
188 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
机器人 2011-04-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 fmfighting 的回复:]

引用 5 楼 fangxinggood 的回复:
你看这个方法有没有在UI上被多个事件被调用,比如窗体的拖拽,最大,最小化,还有方块的运动。


有。那您的意思是被多个事件调用的时候就要lock啊?!那这也属于是多线程吧?
我一直以为用代码创建辅助线程才叫多线程
[/Quote]
方块运动多半是线程在控制(timer),而graphics是重要的资源,所以加锁。
小Fan 2011-04-25
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 fangxinggood 的回复:]
方块运动多半是线程在控制(timer),而graphics是重要的资……
[/Quote]

这个线程是自动创建的么?因为代码中没有自己定义线程
是time在控制方块的运动
Herbert 2011-04-24
  • 打赏
  • 举报
回复
balance 的初始值是1000
用10个线程去减 每个线程减100次 每次1-100随机
肯定是不够减的
如果去掉lock
相当于10个线程一起去减 很可能把lock减成负数 然后抛出异常
加上lock后 第一个线程在运行lock内部的代码时 其他线程在lock外等待
知道第一个线程执行完 第二个线程才去执行lock内容 以此类推
这时线程时安全的

一个很经典的线程同步程序。

而且有个经典的比喻:

比如你到银行拿面额1000元的支票去取钱,银行工作人员查询到账面上有1200元,于是给你1000元,然后将余额修改成200元。

然而,很巧,这个时候另一个人也有一张1000的支票,也在取钱。

你拿出支票,银行A的柜员做查询,1200元。
另一个人同时来到银行B取出1000元,账面还有200元。但是这个银行的柜员不知道。他仍然给你1000元。然后修改金额为200元。

实际上,正确的账面应该是-800元。
小Fan 2011-04-24
  • 打赏
  • 举报
回复
大虾,您就再回答我这个问题吧
小Fan 2011-04-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 fangxinggood 的回复:]
你看这个方法有没有在UI上被多个事件被调用,比如窗体的拖拽,最大,最小化,还有方块的运动。
[/Quote]

有。那您的意思是被多个事件调用的时候就要lock啊?!那这也属于是多线程吧?
我一直以为用代码创建辅助线程才叫多线程
机器人 2011-04-24
  • 打赏
  • 举报
回复
你看这个方法有没有在UI上被多个事件被调用,比如窗体的拖拽,最大,最小化,还有方块的运动。

小Fan 2011-04-24
  • 打赏
  • 举报
回复
不要沉下去啊
小Fan 2011-04-24
  • 打赏
  • 举报
回复
还有个问题额,就是在陈广老师的俄罗斯方块的那个代码里面,
/// <summary>
/// 擦除矩形
/// </summary>
/// <param name="gp"></param>
public void erase(Graphics gp)
{
SolidBrush sb = new SolidBrush(disapperColor);
foreach (Point p in structArr)
{
lock (gp)//这里用到了lock
gp.FillRectangle(sb, PointToRect(p));
}
}
我的理解是,lock是用于多线程访问临界资源异步控制的,那么在代码的其他部分,没有出现创建辅助线程的代码,是不是其他的一些操作会自动创建辅助线程啊?哪些操作会引起自动创建辅助线程呢?
请大家帮帮忙,感激不尽呐
小Fan 2011-04-24
  • 打赏
  • 举报
回复
[Quote=引用楼主 fmfighting 的回复:]
以下是MSDN文档里面的代码,
说用了lock锁住了,balance永远不会小于0,为什么呢?
意思是不是说,只执行lock大括号里面的代码,那个 if (balance < 0)就不执行了?

请知道的人解释清楚一下,非常感谢
using System;
using System.Threading;
class Account
{
private object thisL……
[/Quote]
哦对,我忽视那个产生的随机数最小为1
机器人 2011-04-24
  • 打赏
  • 举报
回复
是让所有进入lock的线程同步执行,

如果异步的话,比如现在 balance = 100;
两个代码块同时进来,那么判断 balance 都是 > 0 的。
两个同时减 amount(假设是100) 的话,balance 不就是-100了。。。

如果同步的话,一个要等另一个结束。
那么第一个 balance - 100 后等于 0.
第二个进来判断 balance 不满足 >= amount 的条件,不就不减了。。。

balance < 0 的异常情况也不会出现了。

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧