C#中的lock关键字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/59590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
lock keyword in C#
提问by David Basarab
I understand the main function of the lock key word from MSDN
我从MSDN上理解lock关键字的主要功能
lock Statement (C# Reference)
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 语句(C# 参考)
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.
请注意,这更像是一个常识性问题,应用程序速度很好,我想知道这是否是将来要遵循的良好设计模式,或者除非绝对需要,否则应该避免这种模式。
采纳答案by Eric
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.
随意锁定所有内容是一种糟糕的设计模式。如果您的代码被随机锁定弄得一团糟,然后您决定使用后台线程进行某些工作,那么您很可能会遇到死锁。在多个线程之间共享资源需要仔细设计,越能隔离棘手的部分越好。
回答by John Christensen
Generally speaking if your application is single threaded, you're not going to get much use out of the lock statement. 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 actuallyknow 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 语句中得到太多用处。不完全了解您的应用程序,我不知道它们是否有用 - 但我怀疑没有。此外,如果您的应用程序在任何地方都使用锁,我不知道我是否会对它在多线程环境中工作充满信心 - 原始开发人员是否真的知道如何开发多线程代码,或者他们只是在各处添加锁定语句,含糊地希望这能奏效?
回答by Quibblesome
There is no point in having locks in the app if there is only one thread and yes, it is a performance hit although it does take a fair number of calls for that hit to stack up into something significant.
如果只有一个线程,那么在应用程序中锁定是没有意义的,是的,这是一个性能损失,尽管它确实需要相当数量的调用才能将该命中累积成重要的东西。
回答by Peter Bernier
You canhave 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..
至于解除锁定。这将取决于代码究竟在做什么。即使它是单线程的,如果您的对象是作为单例实现的,那么您可能会有多个客户端同时使用它的一个实例(在内存中,在服务器上)。
回答by Scott Dorman
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.
使用锁(或任何其他互斥语句或构造)通常只在多线程场景中才需要,在这种场景中,多个线程(您自己创建的或来自您的调用者)有机会与对象交互并更改底层状态或数据维护。例如,如果您有一个可以被多个线程访问的集合,您不希望一个线程在另一个线程试图读取它时通过删除项目来更改该集合的内容。
回答by Yes - that Jake.
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.
Lock(token) 仅用于标记不应在多个线程中同时运行的一个或多个代码块。如果您的应用程序是单线程的,它可以防止出现不存在的情况。
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.
并且锁定确实会导致性能下降,添加指令以在执行代码之前检查同时访问。它应该只在必要时使用。
回答by Pop Catalin
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 线程指南开始
回答by Will Dean
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 窗体计时器)也是如此。
回答by Anthony Mastrean
回答by André Chalella
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 regionsby 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. 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. If the current task is terminated, other tasks could be deadlocked.
例如,考虑一个尝试在持有锁的同时分配内存的任务。如果内存分配失败,中止当前任务不足以保证 AppDomain 的稳定性,因为域中可能有其他任务在等待同一个锁。如果当前任务终止,其他任务可能会死锁。
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() 危险的这篇文章。