多线程的一些注意点

时间:2022-09-08 22:43:06

Thread.Sleep()方法: Sleep是把当前线程挂起多少毫秒。当到了挂起时间是,不意味着当前线程会立即被唤醒。

举个例子:

static object lockObj = new object(); 
static void A()
{
lock (lockObj) //进入就绪队列
{
Thread.Sleep(
1000); Monitor.Pulse(lockObj);
Monitor.Wait(lockObj);
//自我流放到等待队列
}
Console.WriteLine(
"A exit...");
}
static void B()
{
Thread.Sleep(
500);
lock (lockObj) //进入就绪队列
{
Monitor.Pulse(lockObj);
}
Console.WriteLine(
"B exit...");
}
static void C()
{
Thread.Sleep(
750);
lock (lockObj) //进入就绪队列
{

}
Console.WriteLine(
"C exit...");
}
static void Main(string[] args)
{
new Thread(A).Start();
new Thread(B).Start();
new Thread(C).Start();
}

 这个程序输出的顺序:不一定是B,C,A。而是三个顺序都有可能。

第一次我看到的时候,以为输出的顺序一定是B,C,A当时没有理解Sleep的用法。

要想输出的顺序一定是B,C,A的话,可以使用ManualResetEvent,或者AutoResetEvent。

这两个类是用来阻塞线程的,当你需要唤醒的时候,可以通过Set()方法来唤醒阻塞的线程。

ManualResetEvent 当多个线程调用ManualResetEvent.WaitOne()方法以后,调用ManualResetEvent.Set()以后是所有的线程都不阻塞了,并且以后都不阻塞。

AutoResetEvent 多个线程调用waitOne阻塞以后,调用Set方法以后是随机选择一个线程进行释放,并且释放的线程通过一次以后又是阻塞的状态。 下面是利用ManualResetEvent来实现输出的价格必须是B,C,A的顺序。

static void Main(string[] args) 
{
Thread t1
= new Thread(A);
Thread t2
= new Thread(B);
t2.Start();
Thread t3
= new Thread(C);
t2.Join(); t3.Start(); t3.Join();
t1.Start(); t1.Join();
Console.WriteLine(
"cs");
Console.ReadKey();
}

 

线程的调度: Windows下的调度是根据每个线程的优先级进行调度的,优先级跟线程的优先级,饥饿度,占用时间有关系的。

Sleep的意思就是告诉调度器我在这段时间内不会参与竞争资源的调度,当调用Sleep(0)时,会立即进行一个线程优先级的计算,挑选出一个优先级高的线程占用CPU。

Linux下面是根据时间段来的,每个线程执行一段时间,如果在这时间执行完了,就可以提前退出。