请问,这个关于多线程的代码不懂

q2fdaw2 2011-12-08 11:29:18
public class Program
{
static object ball = new object();
public static void Main()
{
Thread threadPing = new Thread(ThreadPingProc);
Thread threadPong = new Thread(ThreadPongProc);
threadPing.Start();
threadPong.Start();
Console.ReadKey();
}
static void ThreadPingProc()
{
lock (ball)
{
for (int i = 0; i < 5; i++)
{
System.Console.WriteLine("张三 ");
Monitor.Wait(ball);
}
}
}
static void ThreadPongProc()
{
lock (ball)
{
for (int i = 0; i < 5; i++)
{
System.Console.WriteLine("李四 ");
Monitor.Pulse(ball);
}
}
}
}


两个问题:
1:首先执行 threadPing.Start();所以,无论如何,第一句都该是"张三"吧,可为什么多执行几次,第一句有时候是"李四"

2:MSDN说的,
Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用。 此话怎讲?我上面的代码似乎就没有这样,没报错呢?
...全文
412 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
阿非 2011-12-09
  • 打赏
  • 举报
回复
就是说进入lock 块内 才对被lock住的对象 有所有权

其他都要等待。

只有有所有权的 才有权利 对被lock 的对象进行 Pulse、PulseAll 和 Wait

其他是没有权利的。 因为lock住的对象的所有权它们没有

q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 sandy945 的回复:]

绕圈圈啊~ 又绕回来了

lock 你知道是什么意思么
[/Quote]
Lock知道啊,互斥锁啊,每次只允许一条线程执行
阿非 2011-12-09
  • 打赏
  • 举报
回复
lock (ball)
{
for (int i = 0; i < 5; i++)
{
System.Console.WriteLine("李四 ");
Monitor.Pulse(ball);
}
}
--------------
这个其实写法是有些问题,虽然它可以work

应该改成


lock (ball)
{
for (int i = 0; i < 5; i++)
{
System.Console.WriteLine("李四 ");
}
Monitor.Pulse(ball);
}

因为for循环在ThreadPongProc的lock (ball){} 中, 就算调用了Monitor.Pulse(ball)

张三也不会输出,因为 ball 在循环结束前一直是锁定状态

所以在循环后调用一次 Monitor.Pulse(ball) 就可以了,告知ThreadPingProc可以继续执行
阿非 2011-12-09
  • 打赏
  • 举报
回复
2:MSDN说的,
Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用。 此话怎讲?我上面的代码似乎就没有这样,没报错呢?
---------------------
lock (ball)
{
Monitor.Wait(ball);
}

lock (ball)
{
Monitor.Pulse(ball);
}
lock 就是同步块
阿非 2011-12-09
  • 打赏
  • 举报
回复
1:首先执行 threadPing.Start();所以,无论如何,第一句都该是"张三"吧,可为什么多执行几次,第一句有时候是"李四"
------------------------
这个不是绝对的,要看CPU的工作情况。 如果碰巧分配时间片的时候顿了一下,那么就不会和你代码的顺序一致了。就是这个不一定是按照你代码的顺序执行的。虽然大多数情况是(CPU低负载)
  • 打赏
  • 举报
回复
至于第二个问题,其实你的程序都是lock而互斥的,在里边写那些代码已经毫无意义了,因为它们根本不可能并发执行。
  • 打赏
  • 举报
回复
threadPing.Start();
threadPong.Start();

这也不过是向系统注册了线程启动要求,这个Start操作立刻结束了,而此时并没有执行你要执行的方法。
阿非 2011-12-09
  • 打赏
  • 举报
回复
绕圈圈啊~ 又绕回来了

lock 你知道是什么意思么
q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 sandy945 的回复:]

引用 13 楼 sandy945 的回复:
因为在lock 内,你才对被lock住的对象有所有权 (hold住?)

你才有权利进行 Pulse、Wait 等方法

你不在同步代码块内,是没权利 Pulse、Wait 的

Pulse和Wait是可以同时进行的
[/Quote]
哦,mygod
那为什么Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用,必须写在Lock块内部?
阿非 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sandy945 的回复:]
因为在lock 内,你才对被lock住的对象有所有权 (hold住?)

你才有权利进行 Pulse、Wait 等方法

你不在同步代码块内,是没权利 Pulse、Wait 的
[/Quote]
Pulse和Wait是可以同时进行的
q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 sandy945 的回复:]

和你写几个lock 没关系,是Pulse、PulseAll 和 Wait 必须写在lock 内

lock 内 Pulse、PulseAll 和 Wait 你可以写多个 也可以不写

不是一定要固定的
[/Quote]
Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用,就是必须写在Lock块内部吗?写在外部为什么不行?
此话的意思,是不是不允许Pulse和Wait同时进行?
阿非 2011-12-09
  • 打赏
  • 举报
回复
和你写几个lock 没关系,是Pulse、PulseAll 和 Wait 必须写在lock 内

lock 内 Pulse、PulseAll 和 Wait 你可以写多个 也可以不写

不是一定要固定的
q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 sandy945 的回复:]

那里不明白?
[/Quote]
我的例子中,Pulse和Wait都是在Lock内部使用的啊,只不过是一个Lock写了一个
这能说明Pulse、PulseAll 和 Wait 方法是从同步的代码块内调用的吗?
还是说,一个Lock语句块内部,必须即写Pulse,又要写Wait
阿非 2011-12-09
  • 打赏
  • 举报
回复
那里不明白?
q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sandy945 的回复:]

因为在lock 内,你才对被lock住的对象有所有权 (hold住?)

你才有权利进行 Pulse、Wait 等方法

你不在同步代码块内,是没权利 Pulse、Wait 的
[/Quote]
我的例子中,Pulse和Wait都是在Lock内部使用的啊,一个Lock一个
q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
我的例子中,Pulse和Wait都是在Lock内部使用的啊,一个Lock一个
阿非 2011-12-09
  • 打赏
  • 举报
回复
因为在lock 内,你才对被lock住的对象有所有权 (hold住?)

你才有权利进行 Pulse、Wait 等方法

你不在同步代码块内,是没权利 Pulse、Wait 的

q2fdaw2 2011-12-09
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 sandy945 的回复:]

Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用。
-------------------------------------------------
同步的代码块指的就是

lock (ball)
{}

你看看你的 Pulse 和 Wait 是不是都在 lock 内调用的
[/Quote]
我就是不明白,为什么Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用?
烟波钓 2011-12-09
  • 打赏
  • 举报
回复
lz是不是从这里摘抄的?http://www.cnblogs.com/free722/archive/2011/03/25/1995136.html
这已经说的很明白了啊
阿非 2011-12-09
  • 打赏
  • 举报
回复
Pulse、PulseAll 和 Wait 方法必须从同步的代码块内调用。
-------------------------------------------------
同步的代码块指的就是

lock (ball)
{}

你看看你的 Pulse 和 Wait 是不是都在 lock 内调用的
加载更多回复(12)

110,502

社区成员

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

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

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