是否存在保证C#中FIFO顺序的同步类?

Ahm*_*aid 15 c# synchronization

它是什么以及如何使用?

我需要它,因为我有一个每秒插入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)

但目前互斥锁并不保证任何订单.我提出详细的问题后没有答案!

Mat*_*ley 31

你需要编写自己的类才能做到这一点,我找到了这个例子(粘贴因为它看起来好像网站的域名已经失效):

using System.Threading;

public sealed class QueuedLock
{
    private object innerLock;
    private volatile int ticketsCount = 0;
    private volatile int ticketToRide = 1;

    public QueuedLock()
    {
        innerLock = new Object();
    }

    public void Enter()
    {
        int myTicket = Interlocked.Increment(ref ticketsCount);
        Monitor.Enter(innerLock);
        while (true)
        {

            if (myTicket == ticketToRide)
            {
                return;
            }
            else
            {
                Monitor.Wait(innerLock);
            }
        }
    }

    public void Exit()
    {
        Interlocked.Increment(ref ticketToRide);
        Monitor.PulseAll(innerLock);
        Monitor.Exit(innerLock);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

QueuedLock queuedLock = new QueuedLock();

try
{
   queuedLock.Enter();
   // here code which needs to be synchronized
   // in correct order
}
finally
{
    queuedLock.Exit();
}
Run Code Online (Sandbox Code Playgroud)

来自Google缓存的来源

  • 如果QueuedLock是IDisposable,这将更漂亮 (4认同)

Jon*_*eet 11

只是阅读Joe Duffy的"Windows上的并发编程",听起来你通常会从.NET监视器中获得FIFO行为,但在某些情况下不会发生这种情况.

本书的第273页说:"因为监视器在内部使用内核对象,它们表现出与OS同步机制也表现出的相同的粗略FIFO行为(在前一章中描述).监视器是不公平的,所以如果另一个线程偷偷摸摸并获得在唤醒等待线程尝试获取锁之前的锁定,允许偷偷摸摸的线程获取锁定."

我无法立即找到"前一章"中引用的部分,但它确实注意到在最近版本的Windows中故意不公平地锁定,以提高可扩展性并减少锁定车队.

你肯定需要你的锁是FIFO吗?也许有一种不同的方式来解决这个问题.我不知道.NET中哪些锁保证是FIFO.

  • 真正有趣的是,“偷偷摸摸的线程”也恰好是刚刚发布监视器的那个。并且,因此,它永远循环下去,使另一个线程挨饿。刚刚在 CE 5 上的 .Net Compact Framework 中使用一些旧代码遇到了这种行为。 (2认同)

JP *_*oto 7

您应该重新设计系统,而不是依赖于线程的执行顺序.例如,让你的线程进行可能需要超过一秒的数据库调用,让你的线程将它们执行的命令放入一个数据结构,如队列(如果有一些东西说"这个应该在另一个之前").然后,在业余时间,排空队列并按正确的顺序一次插入一个db.