我理解来自MSDN的锁定关键字的主要功能
lock语句(C#参考)
lock关键字标记一个语句 阻止作为一个关键部分 获得互斥锁 对于给定的对象,执行一个 声明,然后发布 锁。
什么时候应该使用锁?
例如,它对多线程应用程序有意义,因为它可以保护数据。但是,当应用程序没有脱离任何其他线程时,它是否有必要?
使用锁是否存在性能问题?
我刚刚继承了一个在任何地方使用锁的应用程序,它是单线程的,我想知道我应该留下它们,它们甚至是必要的吗?
请注意,这更多是一般知识问题,申请速度很好,我想知道这是否是一个好的设计模式,或者除非绝对需要,否则应该避免这样做。
答案 0 :(得分:58)
什么时候应该使用锁?
应该使用锁来保护多线程代码中的共享资源。不是别的。
但是当应用程序没有关闭任何其他线程时是否有必要?
绝对不是。这只是浪费时间。但是请确保您没有隐式使用系统线程。例如,如果您使用异步I / O,您可能会收到来自随机线程的回调,而不是原始线程。
使用锁是否存在性能问题?
是。它们在单线程应用程序中不是很大,但为什么要拨打你不需要的电话?
...如果这是一个好的设计模式,将来会有[?]
无所事事地锁定一切都是一种糟糕的设计模式。如果您的代码混乱了随机锁定,然后您决定使用后台线程进行某些工作,那么您可能会遇到死锁。在多个线程之间共享资源需要仔细设计,并且越能分离出棘手的部分,就越好。
答案 1 :(得分:7)
这里的所有答案都是正确的:锁的用处是阻止线程同时访问锁定的代码。但是,这个领域有许多细微之处,其中一个是公共语言运行时自动将锁定的代码块标记为关键区域。
代码被标记为关键的影响是,如果整个区域无法完全执行,运行时可能会认为您的整个Application Domain可能受到危害,因此会从内存中卸载它。引用MSDN:
例如,考虑一个尝试在持有锁时分配内存的任务。如果内存分配失败,则中止当前任务不足以确保AppDomain的稳定性,因为域中可能有其他任务正在等待同一个锁。如果当前任务终止,则其他任务可能会死锁。
因此,即使您的应用程序是单线程的,这也可能对您造成危害。考虑锁定块中的一个方法抛出最终未在块内处理的异常。即使异常发生在它通过调用堆栈冒泡时,您的关键代码区域也无法正常完成。谁知道CLR会如何反应?
有关详细信息,请阅读this article on the perils of Thread.Abort()。
答案 2 :(得分:6)
请记住,可能有理由说明您的应用程序不像您想象的那样是单线程的。例如,.NET中的异步I / O可能会在池线程上回调,就像某些各种计时器类(不是Windows窗体计时器)一样。
答案 3 :(得分:2)
一般来说,如果你的应用程序是单线程的,你就不会在lock语句中得到很多用处。我不确切知道你的应用程序,我不知道它们是否有用 - 但我怀疑不是。此外,如果您的应用程序在任何地方使用锁定,我不知道我会对在多线程环境中工作感到充满信心 - 原始开发人员实际上知道如何开发多线程代码,或者他们只是在模糊的地方添加锁定语句,希望能够解决这个问题吗?
答案 4 :(得分:2)
锁,其他线程同时修改的状态,以及那些其他步骤必须采用相同的锁。
锁实际上是一个内存访问序列化程序,线程(采取锁定)将等待锁进入,直到当前线程退出锁,因此内存访问被序列化。
要回答问题,单线程应用程序中不需要锁定问题,并且确实存在性能副作用。因为C#中的锁是基于内核同步对象的,所以您采取的每个锁都会创建从用户模式到内核模式的转换。
如果您对多线程性能感兴趣,一个好的起点是MSDN threading guidelines
答案 5 :(得分:1)
可能会出现锁定变量的性能问题,但通常情况下,您需要构建代码以最大限度地缩短在“锁定”代码块中花费的时间长度。
至于取下锁。这取决于代码究竟在做什么。即使它是单线程的,如果你的对象被实现为Singleton,你可能会有多个客户端同时使用它的一个实例(在内存中,在服务器上)。
答案 6 :(得分:1)
是的,使用锁时会有一些性能损失,但通常可以忽略不计。
通常只在多线程场景中使用锁(或任何其他互斥语句或构造),其中多个线程(您自己制作或来自您的调用者)有机会与对象交互并更改保持基础状态或数据。例如,如果您有一个可以被多个线程访问的集合,那么您不希望一个线程通过删除一个项来更改该集合的内容,而另一个线程正在尝试读取它。
答案 7 :(得分:1)
Lock(令牌)仅用于标记不应在多个线程中同时运行的一个或多个代码块。如果您的应用程序是单线程的,那么它可以防止不存在的情况。
并且锁定会调用性能命中,添加指令以在执行代码之前检查同时访问。它只应在必要时使用。
答案 8 :(得分:1)
答案 9 :(得分:0)
如果只有一个线程,那么在应用程序中拥有锁是没有意义的,是的,这是一个性能命中,尽管它确实需要相当多的调用才能将该命中堆叠成重要的东西。