我看到,对于使用非线程安全的对象,我们用这样的锁包装代码:
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
Run Code Online (Sandbox Code Playgroud)
那么当多个线程访问相同的代码时会发生什么(让我们假设它在ASP.NET Web应用程序中运行).他们排队了吗?如果是这样,他们会等多久?
使用锁会对性能产生什么影响?
它是什么以及如何使用?
我需要它,因为我有一个每秒插入DB的计时器,我有一个计时器处理程序和主线程之间的共享资源.我想保证,如果计时器处理程序在插入中花费超过一秒钟,则应按顺序执行等待的线程.这是我的计时器处理程序的示例代码
private void InsertBasicVaraibles(object param)
{
try
{
DataTablesMutex.WaitOne();//mutex for my shared resources
//insert into DB
}
catch (Exception ex)
{
//Handle
}
finally
{
DataTablesMutex.ReleaseMutex();
}
}
Run Code Online (Sandbox Code Playgroud)
但目前互斥锁并不保证任何订单.我提出详细的问题后没有答案!
我想知道Monitor Class.据我所知,所有等待的线程都不是FIFO.获取锁的第一个并不是等待队列中的第一个.它是否正确?有没有办法确保FIFO条件?
问候
我需要在C#中编写自己的FIFO /强信号量,使用我自己的信号量类作为基础.我找到了这个例子,但它不是很正确,因为我不应该使用Monitor.Enter/Exit.
这些是我的常规信号量的方法,我想知道是否有一种简单的方法可以使它适应FIFO.
public virtual void Acquire()
{
lock (this)
{
while (uintTokens == 0)
{
Monitor.Wait(this);
}
uintTokens--;
}
}
public virtual void Release(uint tokens = 1)
{
lock (this)
{
uintTokens += tokens;
Monitor.PulseAll(this);
}
}
Run Code Online (Sandbox Code Playgroud) 我要求一部分代码一次只能由一个线程运行(单个资源锁定).
lock(object)C#中的语句允许这样做.但是,它不会保留对锁的请求顺序.
例如,考虑下面的100个线程启动,其中编号的线程尝试按顺序锁定挂锁:
for (int i = 0; i < 100; i++)
{
(new Thread(delegate(object index)
{
int name = (int) index;
byte[] len = new byte[2];
Console.WriteLine(string.Format("Thread:{0} going for lock. ",
name));
lock (padlock)
{
rnd.GetBytes(len);
ushort l = BitConverter.ToUInt16(len, 0);
Console.WriteLine(string.Format("Thread:{0} sleeping: {1}",
name, l));
Thread.Sleep(l);
}
})).Start(i);
Run Code Online (Sandbox Code Playgroud)
实际授予访问权限的顺序并不完美(1-> 100)或NOT FIFO.然而,似乎确实存在"早期早期"EIEO模式(可能由堆运行?).
问题是:什么决定了锁定授予顺序,是否可以依赖于不使不幸的线程挨饿?
更新:这个答案解释了它.这是相关的引用(Joe Duffy在Windows上的并发编程):
因为监视器在内部使用内核对象,所以它们表现出与OS同步机制也表现出的相同的粗略FIFO行为(在前一章中描述).监视器是不公平的,因此如果另一个线程试图在唤醒的等待线程尝试获取锁之前获取锁,则允许偷偷摸摸的线程获取锁.