深入理解.Net中的线程同步之构造模式(二)内核模式构造
前言
Kernel-mode Constructs一般翻译为内核模式构造 ,
Constructs 即是一个名词也是一个动词,但是翻译为构造感觉有点像一个动词,个人感觉翻译为名词更好,毕竟是加了s的,就表示多个,动词显然不能表示多个啊,比如内核模式构造物,内核模式构造体。
环境说明
IDE:Visual Studio 2022
OS:Win10
.NET:.Net4.6.1
一、信号量是什么?
信号量是什么?记得嵌入式的时候老师说过通过0,1来控制线程的阻断和解除阻断就是信号量。这个就是信号量最基础的理解了,信号量其实是由系统内核控制的具有原子性的int变量,为0时阻塞线程,大于0时解除阻塞。
二、代码编写
1.编写一个Semaphone的锁
代码如下(示例):
public class SemaphoreTest
{
public void TestStart()
{
Console.WriteLine(" SemaphoreTest TestStart Start !");
IntObj intObj = new IntObj();
for (Int32 i = 0; i < 10; i++)
{
new TaskFactory().StartNew(() =>
{
AddCount(intObj);
AddCount_SemaphoreLock(intObj);
});
}
Console.WriteLine(" SemaphoreTest TestStart END !");
}
public void AddCount(IntObj intObj)
{
intObj.num_Norml++;
WriteLineThread(intObj);
Thread.Sleep(500);
}
SemaphoreLock tLock = new SemaphoreLock(1);
public void AddCount_SemaphoreLock(IntObj intObj)
{
tLock.Enter();
intObj.num_Lock++;
WriteLineThread_SemaphoreLock(intObj);
Thread.Sleep(500);
tLock.Leave();
tLock.Leave();
}
public void WriteLineThread(IntObj intObj )
{
Thread.Sleep(200);
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"num_Norml :{ intObj.num_Norml},{Thread.CurrentThread.ManagedThreadId}");
Console.ForegroundColor = currentForeColor;
Thread.Sleep(200);
}
public void WriteLineThread_SemaphoreLock(IntObj intObj)
{
Thread.Sleep(200);
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"num_Lock:{ intObj.num_Lock},{Thread.CurrentThread.ManagedThreadId}");
Console.ForegroundColor = currentForeColor;
Thread.Sleep(200);
}
}
2.测试Semaphone锁的效果
代码如下(示例):
public class SemaphoreTest
{
public void TestStart()
{
Console.WriteLine(" SemaphoreTest TestStart Start !");
IntObj intObj = new IntObj();
for (Int32 i = 0; i < 10; i++)
{
new TaskFactory().StartNew(() =>
{
AddCount(intObj);
AddCount_EventLock(intObj);
});
}
Console.WriteLine(" SemaphoreTest TestStart END !");
}
public void AddCount(IntObj intObj)
{
intObj.num_Norml++;
WriteLineThread(intObj);
Thread.Sleep(500);
}
SemaphoreLock tLock = new SemaphoreLock(10);
public void AddCount_EventLock(IntObj intObj)
{
tLock.Enter();
intObj.num_Lock++;
WriteLineThread_EventLock(intObj);
Thread.Sleep(500);
tLock.Leave();
}
public void WriteLineThread(IntObj intObj )
{
Thread.Sleep(200);
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"num_Norml :{ intObj.num_Norml},{Thread.CurrentThread.ManagedThreadId}");
Console.ForegroundColor = currentForeColor;
Thread.Sleep(200);
}
public void WriteLineThread_EventLock(IntObj intObj)
{
Thread.Sleep(200);
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"num_Lock:{ intObj.num_Lock},{Thread.CurrentThread.ManagedThreadId}");
Console.ForegroundColor = currentForeColor;
Thread.Sleep(200);
}
}
效果如下
当信号量锁初始化的时候允许最大10个线程效果
当信号量锁初始化的时候允许最大1个线程效果
此时的结果就和AutoResetEvent事件锁一样的效果了
总结
可以看出,当最大线程数1的时候,信号量和AutoResetEvent事件效果一样。但是信号量的如果多次释放可能会出现SemaphoreFullException的异常。
当最大线程数大于1的时候,将可能有多个线程同时变量。那种情况使用呢?