在C#中locking关键字

我理解MSDN中locking关键字的主要function

locking语句(C#参考)

lock关键字通过获取给定对象的相互排斥锁,执行语句,然后释放锁,将语句块标记为关键部分。

什么时候应该使用锁?

例如,它对于multithreading应用程序是有意义的,因为它保护了数据。 但是,当应用程序不分离任何其他线程时是否有必要?

使用locking是否存在性能问题?

我刚刚inheritance了一个使用锁的应用程序,它是单线程的,我想知道我应该把它们放在哪里,甚至是必要的?

请注意,这是一个更常见的知识问题,应用程序的速度是好的,我想知道,如果这是一个很好的devise模式将来要跟随或应该避免,除非绝对需要。

什么时候应该使用锁?

应该使用锁来保护multithreading代码中的共享资源。 不是别的。

但是,当应用程序不分离任何其他线程时是否有必要?

绝对不。 这只是一个浪费时间。 但是确保你没有隐式使用系统线程。 例如,如果您使用asynchronousI / O,则可能会收到来自随机线程的callback,而不是您的原始线程。

使用locking是否存在性能问题?

是。 在单线程应用程序中它们不是很大,但为什么打不需要的调用呢?

…如果这是一个很好的devise模式,在未来[?]

把所有东西锁在一起是一个糟糕的devise模式。 如果你的代码被随机locking混乱,然后你决定使用后台线程进行一些工作,你很可能会遇到死锁。 在多个线程之间共享资源需要仔细的devise,而越是孤立棘手的部分越好。

这里的所有答案都是正确的:锁的有用性是阻止线程同时访问已locking的代码。 然而,在这个领域有许多微妙之处,其中之一就是locking的代码块被公共语言运行时自动标记为关键区域

代码被标记为关键的影响是,如果整个区域不能完全执行,运行时可能会认为您的整个应用程序域可能受到危害,因此将其从内存中卸载。 引用MSDN :

例如,考虑一个试图在locking时分配内存的任务。 如果内存分配失败,中止当前任务不足以确保AppDomain的稳定性,因为域中可能有其他任务正在等待同一个锁。 如果当前任务被终止,则其他任务可能会死锁。

因此,即使你的应用程序是单线程的,这对你来说可能是危险的。 考虑一个locking块中的一个方法会抛出一个exception,最终在块内不处理。 即使exception是通过调用堆栈来处理的,但是您的关键代码区域并没有正常完成。 谁知道CLR会如何反应?

有关更多信息,请阅读关于Thread.Abort()的风险的文章 。

请记住,您的应用程序不像您想象的那样是单线程的。 .NET中的asynchronousI / O可能会在池线程callback,例如,一些不同的计时器类(不是Windows窗体计时器)。

一般来说,如果您的应用程序是单线程的,那么您将不会从locking语句中获得太多的用处。 不知道你的应用程序,我不知道他们是否有用,但我不怀疑。 而且,如果你的应用程序在任何地方都使用锁,我不知道我是否会对multithreading环境下的工作充满信心 – 原始开发人员是否真的知道如何开发multithreading代码,他们只是在模糊的希望中添加locking语句,这样做会有诀窍吗?

应该在修改共享状态的代码周围使用锁,由其他线程同时修改状态,而其他的状态必须采用相同的锁。

锁实际上是一个内存访问串行器,线程(取得锁)将等待锁进入,直到当前线程退出锁,因此内存访问被序列化。

为了回答你的问题,在一个单线程的应用程序中不需要锁,而且它确实有性能副作用。 因为C#中的locking基于内核同步对象,并且每次执行locking都会从用户模式创build到内核模式的转换。

如果您对multithreading性能感兴趣,那么开始使用MSDN线程指南是一个很好的开始

可能会遇到lockingvariables的性能问题,但是通常情况下,您会构造代码以最小化在“locking”代码块内花费的时间长度。

至于去除锁。 这将取决于代码在做什么。 即使它是单线程的,如果你的对象是作为一个单例实现的,那么你可能会有多个客户同时使用它的一个实例(在内存中,在服务器上)。

是的,在使用locking时会有一些性能损失,但通常可以忽略不计。

使用锁(或任何其他互斥语句或构造)通常只在multithreading场景中需要,在multithreading场景中,多个线程(自己创build或从调用者)有机会与对象进行交互并更改基础状态或数据保持。 例如,如果您有一个可以被多个线程访问的集合,则不希望某个线程通过在另一个线程尝试读取某个项目时删除该项目来更改该集合的内容。

锁(令牌)仅用于标记一个或多个不应该在多个线程中同时运行的代码块。 如果您的应用程序是单线程的,则可以防止不存在的情况。

locking会调用性能命中,并在执行代码之前添加指令以检查同时访问。 只能在必要时使用。

在C#中查看关于“互斥”的问题 。 然后看看这 两个关于使用'lock(Object)'语句的问题。

如果只有一个线程,locking应用程序就没有意义了,是的,尽pipe这个命中需要一定数量的调用来堆砌成重要的东西,