所以我试图研究如何使用多线程,但我发现有些东西我还不太了解。
在下一段代码中,尽管foo与线程相同,但doo()似乎在线程完成之前开始运行。
static void Main(string[] args)
{
new Thread(new ThreadStart(foo)).Start();
foo();
doo();
}
public static void foo()
{
Console.WriteLine("1");
Thread.Sleep(3000);
Console.WriteLine("2");
}
public static void doo()
{
Console.WriteLine("do");
}
输出为:
1个//螺纹
1 // foo
2 // foo
别//斗
2 //螺纹
假设doo()在没有foo()的情况下无法开始运行,我们假定最后的“ 2”输出来自第一个线程。
怎么可能?尽管foo()和Thread由于具有相同的功能而具有相同的睡眠时间,但为什么Thread(首先执行)是最后一个要完成的睡眠?
现在,如果我们增加一个锁的语句,像这样的:
static object syncLock = new object();
static void Main(string[] args)
{
new Thread(new ThreadStart(foo)).Start();
foo();
doo();
}
public static void foo()
{
lock (syncLock)
{
Console.WriteLine("1");
Thread.Sleep(3000);
Console.WriteLine("2");
}
}
public static void doo()
{
Console.WriteLine("do");
}
输出为:
1个//螺纹
2 //螺纹
1 // foo
别//斗
2 //螺纹
现在看来doo()在foo()结束之前开始运行!这是怎么回事流程和背后的逻辑是什么?
答案 0 :(得分:2)
看,您实际上在主线程和第二个线程(foo())上有两个线程。 在 new Thread(new ThreadStart(foo))。Start(); 之后,执行将从主线程开始,这意味着该线程(主线程)将尝试调用foo(),即您的“ 1 “,之后,主线程进入睡眠状态,第二个线程进入星号foo(),即第二个“ 1”,第二秒进入睡眠状态。现在,主线程将醒来并完成工作“ 2”,“ do”,最后的“ 2”来自sec线程。那是没有锁的。
通过锁定,主线程将执行foo(),而sec将被阻止(“ 1”,3sec,“ 2”),这意味着当foo()解锁时,sec线程可以调用foo(),以及发生这种情况,因为sec打印“ 1”广告进入睡眠状态,并且现在(sec正在睡眠中,CPU寻找可以执行的线程),因此CPU exe执行主线程并打印“ do”,然后sec唤醒并打印“ 2“ ..
答案 1 :(得分:0)
如评论中所述,控制台写入将被缓存。
我只是添加了一个数组,然后在最后打印了它的值。
class Program
{
static object syncLock = new object();
static int[] arr = new int[5];
static int counter = 0;
static void Main(string[] args)
{
new Thread(new ThreadStart(foo)).Start();
foo();
doo();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(arr[i]);
}
}
public static void foo()
{
arr[counter] = 1;
counter++;
Thread.Sleep(3000);
arr[counter] = 2;
counter++;
}
public static void doo()
{
arr[counter] = 3;
counter++;
}
}
输出为:
1
1
2
2
3
现在更有意义了。谢谢!有关线程,睡眠和锁的任何其他信息将受到赞赏。