我的学习小组正在讨论一个问题:
(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,则输出(无),因为这会导致死锁
G将是t1锁定b时的输出,然后当t1仍然锁定b时,t2开始,因为t2。Wait表示等待t1完成。
我想不出你怎么可能得到H或HG.然而,我们中的一个人运行了20万次代码,他有时会得到HG…我不明白
我只是不确定这些答案。你们怎么想?任何帮助都非常感谢!
如果您得到一个字母,那就意味着一个线程设法获得了两个锁。这也意味着它将能够释放两个锁,而另一个线程将成功完成——并打印另一个字母。由此推理,GH
和HG
都是可能的输出。另外,也有可能发生死锁,即线程1持有一个锁,线程2持有另一个锁。
不能保证g()
会在h()
之前启动。据我所知,StartNew()
实际上并不启动任务,而是为下一个可用的线程排队。
我认为只得到G或H的唯一方法是让两个函数都完成,但程序在控制台刷新第二个字母之前结束。
可能发生HG,因为无法保证新线程何时开始执行。创建Task t2
后,操作系统可以先运行它,然后返回并运行t1
。