其他分享
首页 > 其他分享> > 链锁?

链锁?

作者:互联网

尝试回答以下question时,我写了这段代码:

using static MyNameSpace.Locker; //So that we don't need to specify the static class name before each call.
public class MainClass
{
    public MainMethod()
    {
        Lock(new object()).Lock(new object()).RunAction(() => Console.WriteLine("Finished"));
    }
}


public static class Locker
{
    public static async Task<List<object>> Lock(object toLock, int timeout = -1)
    {
        await Task.Run(() => TryEnter(toLock, timeout));
        return new List<object>() { toLock };
    }

    public static async Task<List<object>> Lock(
        this Task<List<object>> lockedChain,
        object toLock,
        int timeout = -1)
    {
        await Task.Run(() => TryEnter(toLock, timeout));
        await lockedChain;
        lockedChain.Result.Add(toLock)
        return lockedChain.Result;
    }

    public static async void RunAction(this Task<List<object>> lockChain, Action toRun)
    {
        await lockChain;
        try
        {
            toRun.Invoke();
        }
        finally
        {
            foreach (var chainMember in lockChain.Result)
            {
                Monitor.Exit(chainMember);
            }
        }
    }

    private static void TryEnter(object toLock, int timeout = -1)
    {
        var success = false;
        if (timeout > 0)
        {
            success = Monitor.TryEnter(toLock, timeout);
        }
        else
        {
            success = Monitor.TryEnter(toLock);
        }

        if (!success)
        {
            throw new TimeoutException();
        }
    }
}

但是,正如一些用户正确地指出的那样,这由于非常简单的原因而无法使用:由于这些方法是异步的,因此它们可能无法在同一线程上运行,因此在尝试释放Monitor时会引发异常.

如何确保监视器的Enter和Exit方法在同一线程上运行?

解决方法:

与其强制将锁操作强加到几乎不可能的同一线程上,还应使用非线程仿射的锁:SemaphoreSlim.它还具有本机异步支持(而不是阻止).

在您链接到的原始问题中,我改用this answer.似乎比包含很多人为复杂性的链解决方案更干净.代码质量与所使用的特定调用语法无关.仅仅通过将事物放在句法链中,就不能大大降低复杂性.

特别地,链式解决方案只是说Lock(new [] {lock1,lock2},()=> …);的一种复杂方式.我认为.所有的链条都会建立一个列表.使用使它变得更加简单,因为它消除了lambda. Lambda的可组合性较差,因为您无法像使用中那样从Lambda中返回.我认为您应该针对此目标:

using (MultiLock(new [] { lock1, lock2 }, timeout)) {
 //...
}

标签:multithreading,async-await,c
来源: https://codeday.me/bug/20191118/2028637.html