我创建一个关于线程的例子,
我知道使用锁可以避免在关键部分暂停线程,但我有两个问题。
1.如果我使用Thread.Sleep,为什么我的程序会卡住?
在这个例子中,我将sleep添加到两个线程。
因为我希望控制台输出更慢,所以我可以很容易地看出是否有任何错误。
但是如果我使用Thread.Sleep()那么这个程序就会卡住!
2.我应该在什么情况下使用Thread.Sleep?
感谢您的回复,祝您度过愉快的一天。
class MyThreadExample
{
private static int count1 = 0;
private static int count2 = 0;
Thread t1;
Thread t2;
public MyThreadExample() {
t1 = new Thread(new ThreadStart(increment));
t2 = new Thread(new ThreadStart(checkequal));
}
public static void Main() {
MyThreadExample mt = new MyThreadExample();
mt.t1.Start();
mt.t2.Start();
}
void increment()
{
lock (this)
{
while (true)
{
count1++; count2++;
//Thread.Sleep(0); stuck when use Sleep!
}
}
}
void checkequal()
{
lock (this)
{
while (true)
{
if (count1 == count2)
Console.WriteLine("Synchronize");
else
Console.WriteLine("unSynchronize");
// Thread.Sleep(0);
}
}
}
}
答案 0 :(得分:0)
请查看以下代码。永远不要使用lock(this),而是使用lock(syncObj),因为你可以更好地控制它。仅锁定临界区(例如:仅变量)并且不要锁定整个while循环。在方法Main中,添加要在“Console.Read()”结束时等待的内容,否则,您的应用程序已经死了。这个可以使用或不使用Thread.Sleep。在上面的代码中,您的线程将输入“Increment”或“Checkequal”,锁将永远不会释放。这就是为什么,它仅适用于Increment或Checkequal,而不适用于两者。
internal class MyThreadExample
{
private static int m_Count1;
private static int m_Count2;
private readonly object m_SyncObj = new object();
private readonly Thread m_T1;
private readonly Thread m_T2;
public MyThreadExample()
{
m_T1 = new Thread(Increment) {IsBackground = true};
m_T2 = new Thread(Checkequal) {IsBackground = true};
}
public static void Main()
{
var mt = new MyThreadExample();
mt.m_T1.Start();
mt.m_T2.Start();
Console.Read();
}
private void Increment()
{
while (true)
{
lock (m_SyncObj)
{
m_Count1++;
m_Count2++;
}
Thread.Sleep(1000); //stuck when use Sleep!
}
}
private void Checkequal()
{
while (true)
{
lock (m_SyncObj)
{
Console.WriteLine(m_Count1 == m_Count2 ? "Synchronize" : "unSynchronize");
}
Thread.Sleep(1000);
}
}
}
线程有点老式。如果您是.NET的初学者并使用.NET 4.5或更高版本,请使用Task。好多了。 .NET中的所有新多线程都基于Task,如异步等待:
public static void Main()
{
var mt = new MyThreadExample();
Task.Run(() => { mt.Increment(); });
Task.Run(() => { mt.Checkequal(); });
Console.Read();
}