为什么AsyncLock内的锁不会阻塞线程? [英] Why the lock inside AsyncLock does not block the thread?

查看:595
本文介绍了为什么AsyncLock内的锁不会阻塞线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解 AsyncLock 有效.

首先,下面的代码片段可以证明它确实有效:

First of all, here's a snippet to prove that it actually works:

var l = new AsyncLock();
var tasks = new List<Task>();
while (true)
{
    Console.ReadLine();
    var i = tasks.Count + 1;
    tasks.Add(Task.Run(async () =>
    {
        Console.WriteLine($"[{i}] Acquiring lock ...");
        using (await l.LockAsync())
        {
            Console.WriteLine($"[{i}] Lock acquired");
            await Task.Delay(-1);
        }
    }));
}

有效"是指您可以运行任意数量的任务(通过按Enter键),并且线程数不会增加.如果将其替换为传统的lock,您会看到新线程已启动,这是我们尝试避免的方法.

By "works" I mean that you can run as many tasks as you want (by hitting Enter) and the number of threads doesn't grow. If you replace it with traditional lock, you'll see that the new threads are started, which is what we try to avoid.

但是您在源代码中看到的第一件事是...

But the first thing you see in the source code is... the lock

有人可以请我解释一下它是如何工作的,为什么它不能阻止,以及我在这里想念的是什么吗?

Can somebody please explain me how this works, why it doesn't block, and what am I missing here?

推荐答案

有人可以请我解释一下它是如何工作的,为什么它不能阻止,以及我在这里想念的是什么吗?

Can somebody please explain me how this works, why it doesn't block, and what am I missing here?

简短的回答是,lock只是用于确保线程安全的内部机制. lock绝不会以任何方式公开,并且任何线程都无法在任何实际时间内持有该锁.这样,它类似于各种并发集合在内部使用的锁.

The short answer is that lock is just an internal mechanism used to guarantee thread safety. The lock is never exposed in any way, and there's no way for any thread to hold that lock for any real amount of time. In this way, it's similar to the locks used internally by various concurrent collections.

还有一种使用无锁编程的方法,但是我发现无锁编程非常难于编写,读取和维护.一个很好的例子(可惜不是在线的)是Dobb博士在90年代后期发表的许多文章,每一篇都试图通过更好的无锁队列实现来超越最后一篇.事实证明它们都是错误的-在某些情况下,发现这些错误需要十多年的时间.

There is an alternate approach that uses lock-free programming, but I have found lock-free programming to be extremely difficult to write, read, and maintain. A great example of this (which is sadly not online) was a bunch of Dr. Dobb's articles in the late '90s, each one trying to out-do the last with a better lock-free queue implementation. It turns out they were all faulty - in some cases, the bugs took more than a decade to find.

对于我自己的代码,我不使用无锁编程,除非代码的正确性显而易见.

For my own code, I do not use lock-free programming, except where the correctness of the code is trivially obvious.

就异步锁与锁的概念而言,我将尝试说明一下.我有一种感觉,我只有在使用异步协调原语时才有这种感觉.关于撰写博客文章,我已经进行了很多思考,但是我没有正确的措辞以使其易于理解.就是说,这里...

As far as the async lock vs lock concepts, I'm going to take a stab at explaining this. There's a feeling I get that I have only felt when working with asynchronous coordination primitives. It's something I've thought a lot about writing a blog post on, but I don't have the right words to make it understandable. That said, here goes...

异步协调原语存在于与普通协调原语完全不同的平面上.同步原语阻塞线程和信号线程.异步原语仅适用于普通对象;阻止或发信号只是按照惯例".

Asynchronous coordination primitives exist on a completely different plane than normal coordination primitives. Synchronous primitives block threads and signal threads. Asynchronous primitives just work on plain objects; the blocking or signaling is just "by convention".

因此,对于普通的lock,调用代码必须立即获得锁定.但是对于异步锁",尝试的锁只是一个请求,只是一个对象.调用代码甚至不需要await它.可以请求几个锁,然后将awaitTask.WhenAll一起使用.甚至将它们与其他事物结合在一起;代码可以做一些疯狂的事情,例如(a)等待两个锁都释放以便发送信号(例如AsyncManualResetEvent),然后在信号首先进入时取消锁请求

So, with a normal lock, the calling code must take the lock immediately. But with an asynchronous "lock", the attempted lock is just a request, just an object. The calling code doesn't even need to await it. It's possible to request several locks and await them all together with Task.WhenAll. Or even combine them with other things; code can do crazy things like (a)wait for two locks to both be free or for a signal (like AsyncManualResetEvent) to be sent, and then cancel the lock requests if the signal comes in first.

从线程角度看,这有点像用户模式线程调度.协作式多任务处理也有一些相似之处(相对于抢占式).但总的来说,异步原语被提升"到另一平面,在该平面中,仅可处理对象和代码块,而不处理线程.

From a thread perspective, it's kinda-sorta like user-mode thread scheduling. There's also some similarities to cooperative multitasking (as opposed to preemptive). But overall, the asynchronous primitives are "lifted" to a different plane, where one works only with objects and blocks of code, not threads.

这篇关于为什么AsyncLock内的锁不会阻塞线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆