多线程锁定,欢乐时光(期中练习)
这是我的学习小组正在争论的一个问题:
(g) 考虑以下 C# 代码:
public class Demo {
private static readonly object a = new object();
private static readonly object b = new object();
public static void Main (string[] args) {
Demo d = new Demo();
Task t1 = Task.Factory.StartNew(d.g);
Task t2 = Task.Factory.StartNew(d.h);
t2.Wait();
t1.Wait();
}
private void g() {
lock (a) {
lock (b) {
Console.Write("G");
}
}
}
private void h() {
lock (b) {
lock (a) {
Console.Write("H");
}
}
}
}
这是一个多线程程序,因此不同的执行可能会产生不同的结果。在程序可能产生的完整输出旁边放置一个复选标记。 (最后一个选择代表没有输出。) 输出答案
输出-----可以吗?
GH
HG
G
H
(nothing)
我们的想法:
如果 t1 在 t2 锁定 b 之前锁定 b,则 GH 将是输出。
如果 t1 锁定 a,然后 t2 锁定 b,则输出为(无),因为这会导致死锁
如果 t1 锁定 b,则输出 G 将是输出,然后当 t1 仍持有对 b 的锁定时,t2 启动,因为 t2 .wait 将等待 t1 完成。
无法想象你怎么可能得到 H 或 HG。然而,我们中的一个人运行了代码 200,000 次,有时他会得到 HG...我不明白,
但我只是不确定这些答案。大家觉得怎么样?非常感谢任何帮助!
Here is a question my study group is arguing about:
(g) Consider the following C# code:
public class Demo {
private static readonly object a = new object();
private static readonly object b = new object();
public static void Main (string[] args) {
Demo d = new Demo();
Task t1 = Task.Factory.StartNew(d.g);
Task t2 = Task.Factory.StartNew(d.h);
t2.Wait();
t1.Wait();
}
private void g() {
lock (a) {
lock (b) {
Console.Write("G");
}
}
}
private void h() {
lock (b) {
lock (a) {
Console.Write("H");
}
}
}
}
This is a multi-threaded program, so different executions may produce different results. Place a check-mark next to the complete output that the program might produce. (The last choice stands for no output.)
Output Answer
Output-------Possible?
GH
HG
G
H
(nothing)
What we think:
GH would be the output if t1 locked b before t2 locked b.
(nothing) would be the output if t1 locked a and then t2 locked b, because it would cause a deadlock
G would be the output if t1 locked b, and then while t1 still held the lock on b, t2 started, because the t2.wait would be waiting on t1 to finish.
Can’t think of how you could possibly get H or HG. However, one of us ran the code 200,000 times, and he got HG sometimes... I don't understand
I just don't feel certain about these answers though. What do you all think? Any help is greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您收到一个字母,则意味着一个线程设法获得了两个锁。这也意味着它将能够释放两个锁,并且另一个线程将成功完成 - 并打印另一个字母。根据这个推理,
GH
和HG
都是可能的输出。此外,还可能遇到死锁情况,其中线程 1 持有一个锁,而线程 2 持有另一个锁。If you are ever getting a single letter, that means one thread managed to obtain both locks. Which also means it will be able to release both locks, and the other thread will complete successfully - and print the other letter. With this reasoning, both
GH
andHG
are possible outputs. Also, it is possible to hit the deadlock case, where thread 1 holds one lock, and thread 2 holds the other.绝对不能保证
g()
会在h()
之前启动。据我了解,StartNew()
实际上并不启动任务,而是将其排队等待下一个可用线程。There is absolutely no guarantee that
g()
will be started beforeh()
. As I understand theStartNew()
doesn't actually start the task, but rather queues it up for the next available thread.我认为仅获得 G 或仅 H 的唯一方法是完成两个函数,但程序在控制台刷新第二个字母之前结束。
I think the only way to get only G or only H is to have both function finish, but the program ends before the console flushes second letter.
HG 可能会发生,因为无法保证新线程何时开始执行。创建
Task t2
后,操作系统可以先运行它,然后返回并运行t1
。HG can happen because there is no guarantee of when a new thread starts to execute. After creating
Task t2
the operating system is free to run it first, then go back and runt1
.