多线程同步的正确模式? (C#)
我有两个线程引用同一个变量——UI 线程和计时器线程。因此,我将对它的访问包装在两个线程中的锁定语句中。计时器线程的访问具有优先级——如果它正在使用变量并且 UI 线程也想要访问,我希望 UI 线程的操作完成,但只有在计时器线程的操作完成之后。
但是,计时器线程可能委托回 UI 线程,因此 UI 线程需要有空闲来处理该问题。为了适应这种情况,我让 UI 线程启动第三个线程来处理其操作,以便它(第三个线程)可以等待计时器操作完成并且 UI 线程可用。锁定发生在第三个线程中。
我应该使用什么正确的模式来进行这种同步?
I have two threads referencing the same variable -- the UI thread and a timer thread. As such, I have wrapped access to it in lock statements in both threads. The timer thread's access has priority -- if it's using the variable and the UI thread also wants access, I want the UI thread's operation to complete, but only after the timer thread's operation completes.
However, the timer thread may delegate back to the UI thread, so the UI thread needs to be free to handle that. To accommodate that, I have the UI thread launching a third thread to handle its operation so that it (that third thread) can wait for the timer operation to complete and the UI thread can be available. The locking happens in that third thread.
What is the correct pattern I should be using for this sort of synchronization?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一般建议是关键部分发生的任何事情都应该尽可能简单。特别是您应该避免嵌套锁。嵌套锁可能是死锁的根源。
当应用于您在“计时器”线程中所做的事情时,您可能应该将关键部分与处理分开。定时器线程中的 IOW 只是从公共变量中检索数据,然后执行其余处理,包括与锁外的 UI 线程交互。
添加第三个线程不会让你的生活变得更轻松
The general recommendation is that whatever is happening in critical sections should be as simple as possible. In particular you should avoid nested locks. Nested locks potentially are the source of deadlocks.
As applied to what you are doing in your 'timer' thread you probably should separate the critical sections from processing. IOW in the timer thread just retrieve the data from the common variable(s) and then do the rest of the processing including interactions with UI thread outside the lock.
Adding a third thread to the mix will not make your life any easier
经验法则是在尽可能最短时间内使用最轻锁。
这里有一篇相当好的文章:http://www. moserware.com/2008/09/how-do-locks-lock.html
The rule of thumb is to use the lightest lock for the shortest time possible.
There is quite a good article here: http://www.moserware.com/2008/09/how-do-locks-lock.html
要遵循的一般规则是,尽量减少持有锁的时间,并且在持有锁时不要调用不属于您自己和控制的代码(例如事件、虚拟方法或 UI 线程)一把锁。
因此,计时器在持有锁时不应回调 UI。如果它需要对锁定下的数据进行事务访问(读取、调用 UI、写入),那么它可能应该设计为回滚和/或重试。
A general rule to follow is that you minimize the amount of time that you hold a lock, and you don't call code you don't own and control (such as an event, a virtual method, or a UI thread) while holding a lock.
So the timer should not call back into the UI while holding the lock. If it needs transactional access to the data under the lock (read, call UI, write), then it should probably be designed to roll back and/or retry.
就像 mfeingold 所说,尽可能避免它。如果无法避免,请注意以相同的顺序获取两个线程中的锁!我的意思是,如果你有三个锁 A、B 和 C,如果你有以下锁模式
那么死锁是可能的。 ..
嵌套锁通常会降低性能,因为您必须锁定外部锁,即使有时不需要确保从另一个线程调用该方法的情况下的正确行为。
Like mfeingold said, avoid it where possible. Where you cannot avoid it take care of taking the locks in both threads in the same order! I mean, if you have three locks A, B and C, if you have following lock patterns
then a deadlock is possible...
Nesting locks usually costs performance as you have to lock the outer locks even if you would sometimes not need to to ensure correct behavior in the case where the method is called from another thread.
你为什么要这样做?听起来很复杂而且容易出错。
计时器线程委托给 UI 线程的目的是什么?
情况可能是这样,但我的第一反应是,您可能需要退后一步,考虑一下您的设计是否不必要地迫使您陷入复杂的同步问题。
Why are you doing this? It sounds complicated and error prone.
What is the timer thread delegating to the UI thread for?
It may be the case that it's necessary, but my immediate reaction is that you probably need to take a step back and consider whether your design is unnecessarily forcing you into complex synchronization issues.