简体   繁体   English

在C#中锁定关键字

[英]lock keyword in C#

I understand the main function of the lock key word from MSDN 我理解来自MSDN的锁定关键字的主要功能

lock Statement (C# Reference) lock语句(C#参考)

The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock. lock关键字通过获取给定对象的互斥锁,执行语句,然后释放锁来将语句块标记为关键部分。

When should the lock be used? 什么时候应该使用锁?

For instance it makes sense with multi-threaded applications because it protects the data. 例如,它对多线程应用程序有意义,因为它可以保护数据。 But is it necessary when the application does not spin off any other threads? 但是,当应用程序没有关闭任何其他线程时,它是否有必要?

Is there performance issues with using lock? 使用锁存在性能问题吗?

I have just inherited an application that is using lock everywhere, and it is single threaded and I want to know should I leave them in, are they even necessary? 我刚刚继承了一个在任何地方使用锁的应用程序,它是单线程的,我想知道我应该留下它们,它们甚至是必要的吗?

Please note this is more of a general knowledge question, the application speed is fine, I want to know if that is a good design pattern to follow in the future or should this be avoided unless absolutely needed. 请注意,这更多是一般知识问题,应用程序速度很好,我想知道这是否是将来要遵循的良好设计模式,或者除非绝对需要,否则应该避免这种情况。

When should the lock be used? 什么时候应该使用锁?

A lock should be used to protect shared resources in multithreaded code. 应使用锁来保护多线程代码中的共享资源。 Not for anything else. 不是别的。

But is it necessary when the application does not spin off any other threads? 但是,当应用程序没有关闭任何其他线程时,它是否有必要?

Absolutely not. 绝对不。 It's just a time waster. 这只是浪费时间。 However do be sure that you're not implicitly using system threads. 但是请确保您没有隐式使用系统线程。 For example if you use asynchronous I/O you may receive callbacks from a random thread, not your original thread. 例如,如果您使用异步I / O,您可能会收到来自随机线程的回调,而不是原始线程。

Is there performance issues with using lock? 使用锁存在性能问题吗?

Yes. 是。 They're not very big in a single-threaded application, but why make calls you don't need? 它们在单线程应用程序中不是很大,但为什么要拨打你不需要的电话呢?

...if that is a good design pattern to follow in the future[?] ......如果这是一个很好的设计模式,将来会跟进[?]

Locking everything willy-nilly is a terrible design pattern. 无所事事地锁定一切都是一种糟糕的设计模式。 If your code is cluttered with random locking and then you do decide to use a background thread for some work, you're likely to run into deadlocks. 如果您的代码混乱了随机锁定,然后您决定使用后台线程进行某些工作,那么您可能会遇到死锁。 Sharing a resource between multiple threads requires careful design, and the more you can isolate the tricky part, the better. 在多个线程之间共享资源需要仔细设计,并且越能分离出棘手的部分就越好。

All the answers here seem right: locks' usefulness is to block threads from acessing locked code concurrently. 这里的所有答案都是正确的:锁的用处是阻止线程同时访问锁定的代码。 However, there are many subtleties in this field, one of which is that locked blocks of code are automatically marked as critical regions by the Common Language Runtime. 但是,这个领域有许多细微之处,其中之一就是公共语言运行时自动将锁定的代码块标记为关键区域

The effect of code being marked as critical is that, if the entire region cannot be entirely executed, the runtime may consider that your entire Application Domain is potentially jeopardized and, therefore, unload it from memory. 代码被标记为关键的影响是,如果整个区域无法完全执行,运行时可能会认为您的整个Application Domain可能受到危害,因此会从内存中卸载它。 To quote MSDN : 引用MSDN

For example, consider a task that attempts to allocate memory while holding a lock. 例如,考虑一个尝试在持有锁时分配内存的任务。 If the memory allocation fails, aborting the current task is not sufficient to ensure stability of the AppDomain, because there can be other tasks in the domain waiting for the same lock. 如果内存分配失败,则中止当前任务不足以确保AppDomain的稳定性,因为域中可能有其他任务正在等待同一个锁。 If the current task is terminated, other tasks could be deadlocked. 如果当前任务终止,则其他任务可能会死锁。

Therefore, even though your application is single-threaded, this may be a hazard for you. 因此,即使您的应用程序是单线程的,这可能对您有害。 Consider that one method in a locked block throws an exception that is eventually not handled within the block. 考虑锁定块中的一个方法抛出最终未在块内处理的异常。 Even if the exception is dealt as it bubbles up through the call stack, your critical region of code didn't finish normally. 即使异常发生在它通过调用堆栈冒泡时,您的关键代码区域也无法正常完成。 And who knows how the CLR will react? 谁知道CLR会如何反应?

For more info, read this article on the perils of Thread.Abort() . 有关更多信息,请阅读本文关于Thread.Abort()的危险

Bear in mind that there might be reasons why your application is not as single-threaded as you think. 请记住,可能有原因导致您的应用程序不像您想象的那样是单线程的。 Async I/O in .NET may well call-back on a pool thread, for example, as do some of the various timer classes (not the Windows Forms Timer, though). 例如,.NET中的异步I / O可能会在池线程上回调,就像一些各种计时器类(不是Windows窗体计时器)一样。

Generally speaking if your application is single threaded, you're not going to get much use out of the lock statement. 一般来说,如果你的应用程序是单线程的,那么你不会在lock语句中得到很多用处。 Not knowing your application exactly, I don't know if they're useful or not - but I suspect not. 我不确切知道你的应用程序,我不知道它们是否有用 - 但我怀疑不是。 Further, if you're application is using lock everywhere I don't know that I would feel all that confident about it working in a multi-threaded environment anyways - did the original developer actually know how to develop multi-threaded code, or did they just add lock statements everywhere in the vague hope that that would do the trick? 此外,如果您的应用程序在任何地方都使用锁,我不知道我会对在多线程环境中工作感到充满信心 - 原始开发人员是否真的知道如何开发多线程代码,或者他们只是在模糊的希望中添加锁定语句,希望能够解决这个问题吗?

lock should be used around the code that modifies shared state, state that is modified by other threads concurrently, and those other treads must take the same lock. 应该在修改共享状态的代码周围使用锁,同时修改由其他线程修改的状态,并且那些其他步骤必须采用相同的锁。

A lock is actually a memory access serializer, the threads (that take the lock) will wait on the lock to enter until the current thread exits the lock, so memory access is serialized. 锁实际上是一个内存访问序列化程序,线程(采取锁定)将等待锁进入,直到当前线程退出锁,因此内存访问被序列化。

To answer you question lock is not needed in a single threaded application, and it does have performance side effects. 为了回答你的问题,单线程应用程序中不需要锁定问题,它确实会产生性能副作用。 because locks in C# are based on kernel sync objects and every lock you take creates a transition to kernel mode from user mode. 因为C#中的锁是基于内核同步对象的,所以您采取的每个锁都会创建从用户模式到内核模式的转换。

If you're interested in multithreading performance a good place to start is MSDN threading guidelines 如果您对多线程性能感兴趣,一个好的起点是MSDN线程指南

You can have performance issues with locking variables, but normally, you'd construct your code to minimize the lengths of time that are spent inside a 'locked' block of code. 锁定变量可能会出现性能问题,但通常情况下,您需要构建代码以最大限度地缩短在“锁定”代码块中花费的时间长度。

As far as removing the locks. 至于取下锁。 It'll depend on what exactly the code is doing. 这将取决于究竟是什么代码正在做什么。 Even though it's single threaded, if your object is implemented as a Singleton, it's possible that you'll have multiple clients using an instance of it (in memory, on a server) at the same time.. 即使它是单线程的,如果你的对象被实现为Singleton,你可能会有多个客户端同时使用它的一个实例(在内存中,在服务器上)。

Yes, there will be some performance penalty when using lock but it is generally neglible enough to not matter. 是的,使用锁时会有一些性能损失,但通常可以忽略不计。

Using locks (or any other mutual-exclusion statement or construct) is generally only needed in multi-threaded scenarios where multiple threads (either of your own making or from your caller) have the opportunity to interact with the object and change the underlying state or data maintained. 使用锁(或任何其他互斥语句或构造)通常仅在多线程场景中需要,其中多个线程(您自己制作或来自调用者)有机会与对象交互并更改基础状态或数据维持。 For example, if you have a collection that can be accessed by multiple threads you don't want one thread changing the contents of that collection by removing an item while another thread is trying to read it. 例如,如果您有一个可以被多个线程访问的集合,则您不希望一个线程通过在另一个线程尝试读取它时删除该项来更改该集合的内容。

Lock(token) is only used to mark one or more blocks of code that should not run simultaneously in multiple threads. 锁(令牌)仅用于标记不应在多个线程中同时运行的一个或多个代码块。 If your application is single-threaded, it's protecting against a condition that can't exist. 如果您的应用程序是单线程的,那么它可以防止不存在的情况。

And locking does invoke a performance hit, adding instructions to check for simultaneous access before code is executed. 并且锁定会调用性能命中,添加指令以在执行代码之前检查同时访问。 It should only be used where necessary. 它只应在必要时使用。

See the question about 'Mutex' in C#. 在C#中查看有关“Mutex”的问题 And then look at these two questions regarding use of the 'lock(Object)' statement specifically. 然后专门看一下有关使用'lock(Object)'语句的 两个问题。

如果只有一个线程,那么在应用程序中拥有锁是没有意义的,是的,这是一个性能命中,尽管它确实需要相当多的调用才能将该命中重叠成重要的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM