49 c# multithreading
我有理解困难时期 Wait(),Pulse(),PulseAll().他们都会避免僵局吗?如果您解释如何使用它们,我将不胜感激?
Mar*_*ell 55
精简版:
lock(obj) {...}
Run Code Online (Sandbox Code Playgroud)
是(Monitor.Enter/ Monitor.Exit有异常处理等)的简写.如果没有其他人拥有锁,你可以得到它(并运行你的代码) - 否则你的线程被阻塞,直到获得锁(由另一个线程释放它).
当A:两个线程以不同的顺序锁定事物时,通常会发生死锁:
thread 1: lock(objA) { lock (objB) { ... } }
thread 2: lock(objB) { lock (objA) { ... } }
Run Code Online (Sandbox Code Playgroud)
(在这里,如果他们每获得第一锁,也不能永远获得第二,因为没有线程可以退出来释放自己的锁)
总是以相同的顺序锁定可以最小化这种情况; 并且您可以通过使用Monitor.TryEnter(而不是Monitor.Enter/ lock)并指定超时来恢复(到某种程度).
或者B:你可以在持有锁的情况下切换线程时使用winforms这样的东西:
lock(obj) { // on worker
this.Invoke((MethodInvoker) delegate { // switch to UI
lock(obj) { // oopsiee!
...
}
});
}
Run Code Online (Sandbox Code Playgroud)
上面的僵局显而易见,但是当你有意大利面条代码时它并不那么明显; 可能的答案:不要在持有锁的情况下进行线程切换,或者使用BeginInvoke以便至少可以退出锁(让UI播放).
Wait/ Pulse/ PulseAll是不同的; 它们用于发信号.我在这个答案中使用这个信号,以便:
Dequeue:如果您在队列为空时尝试将数据出列,它会等待另一个线程添加数据,从而唤醒被阻塞的线程Enqueue:如果您在队列已满时尝试将数据入队,它会等待另一个线程删除数据,从而唤醒被阻塞的线程Pulse只唤醒一个线程 - 但我不够聪明,不能证明下一个线程始终是我想要的,所以我倾向于使用PulseAll,只是在继续之前重新验证条件; 举个例子:
while (queue.Count >= maxSize)
{
Monitor.Wait(queue);
}
Run Code Online (Sandbox Code Playgroud)
使用这种方法,我可以安全地添加其他含义Pulse,而不是我现有的代码假设"我醒了,因此有数据" - 这在(稍后)需要添加Close()方法的时候很方便.
gat*_*ich 43
使用Monitor.Wait和Monitor.Pulse的简单配方.它由工人,老板和他们用来沟通的电话组成:
object phone = new object();
Run Code Online (Sandbox Code Playgroud)
一个"工人"线程:
lock(phone) // Sort of "Turn the phone on while at work"
{
while(true)
{
Monitor.Wait(phone); // Wait for a signal from the boss
DoWork();
Monitor.PulseAll(phone); // Signal boss we are done
}
}
Run Code Online (Sandbox Code Playgroud)
一个"老板"线程:
PrepareWork();
lock(phone) // Grab the phone when I have something ready for the worker
{
Monitor.PulseAll(phone); // Signal worker there is work to do
Monitor.Wait(phone); // Wait for the work to be done
}
Run Code Online (Sandbox Code Playgroud)
更复杂的例子如下......
"有其他事可做的工人":
lock(phone)
{
while(true)
{
if(Monitor.Wait(phone,1000)) // Wait for one second at most
{
DoWork();
Monitor.PulseAll(phone); // Signal boss we are done
}
else
DoSomethingElse();
}
}
Run Code Online (Sandbox Code Playgroud)
一个"不耐烦的老板":
PrepareWork();
lock(phone)
{
Monitor.PulseAll(phone); // Signal worker there is work to do
if(Monitor.Wait(phone,1000)) // Wait for one second at most
Console.Writeline("Good work!");
}
Run Code Online (Sandbox Code Playgroud)
Vit*_*sky 10
不,他们不能保护你免受僵局.它们只是用于线程同步的更灵活的工具.这里有一个非常好的解释如何使用它们和非常重要的使用模式 - 没有这种模式你将打破所有的东西:http: //www.albahari.com/threading/part4.aspx
| 归档时间: |
|
| 查看次数: |
44670 次 |
| 最近记录: |