use*_*498 54 c# multithreading locking
我有3个问题需要帮助.
作为lock语句参数传递的正确对象/引用是什么?我已经看过很多示例代码,我注意到传入的对象/引用可能与当前类或程序中的任何其他类无关,只要访问修饰符static不公开?例如:
private Object anyObj = new Object();
lock(anyObj){.....}
private static readonly object Locker = new object();
lock(Locker){.....}
Run Code Online (Sandbox Code Playgroud)
这对我来说没有意义.
我在MSDN中找到了一个关于使用lock语句的多线程的示例代码.在样本中有两个try/ catch块Monitor.Wait().如果我正确理解逻辑,那么readerFlag将禁止程序进入try/ catchblock.
代码是示例2从这里:http:
//msdn.microsoft.com/en-us/library/aa645740(v = vs.71).aspx
只要Windows窗体处于活动状态,如何运行在后台运行的线程?
pli*_*nth 75
你如何以及如何锁定取决于你正在做什么.
假设您正在使用某种设备 - 比如咖啡机.您可能有一个如下所示的类:
public CoffeeMaker {
private IntPtr _coffeeHandle;
private Object _lock = new Object();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您正在保护对_coffeeHandle的访问 - 对真实物理设备的指针/句柄,所以这很容易:
public int AvailableCups {
get {
lock (_lock) {
return GetAvailableCups(_coffeeHandle); // P/Invoked
}
}
}
public void Dispense(int nCups)
{
lock (_lock) {
int nAvail = GetAvailableCups(_coffeeHandle);
if (nAvail < nCups) throw new CoffeeException("not enough coffee.");
Dispense(_coffeeHandle, nCups); // P/Invoked
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我正在运行多线程应用程序,我(可能)不想读取我在分配时可用的杯数(可能是硬件错误).通过保护对句柄的访问,我可以确保.另外,在我已经配药的时候,我不能被要求免除 - 这会很糟糕,所以它也受到了保护.最后,除非我有足够的咖啡,否则你不会放弃,而且你注意到我没有使用我的公共财产来检查 - 这样一来,确保咖啡和分配足够的作用就会被捆绑在一起.神奇的词是原子的 - 它们不能在不产生问题的情况下被分开.
如果您只有一个需要保护的资源实例,则使用静态对象作为锁.想想,"我有一个单身人士吗?" 这将是您何时需要静态锁定的指南.例如,假设CoffeeMaker有一个私有构造函数.相反,您有一个构建咖啡机的工厂方法:
static Object _factLock = new Object();
private CoffeeMaker(IntPtr handle) { _coffeeHandle = handle; }
public static CoffeeMaker GetCoffeeMaker()
{
lock (_factLock) {
IntPtr _handle = GetCoffeeMakerHandle(); // P/Invoked
if (_handle == IntPtr.Zero) return null;
return new CoffeeMaker(_handle);
}
}
Run Code Online (Sandbox Code Playgroud)
现在在这种情况下,感觉CoffeeMaker应该实现IDisposable,以便处理句柄,因为如果你不释放它,那么有人可能没有得到他们的咖啡.
但是有一些问题 - 也许如果没有足够的咖啡,我们应该做更多 - 这需要很长时间.哎呀 - 分配咖啡需要很长时间,这就是为什么我们要小心保护我们的资源.现在你认为真的所有这些咖啡机的东西应该是自己的一个线程,并且应该有一个事件在咖啡完成后被解雇,然后它开始变得复杂,你明白了解知识的重要性什么你锁定什么,什么时候你不要阻止煮咖啡因为你问了多少杯.
如果"死锁","原子","监视器","等待"和"脉冲"这些词对你来说都很陌生,你应该考虑阅读一般的多处理/多线程,看看你是否可以解决这个公平的理发店问题或餐饮哲学家问题,这两个都是资源争用的典型例子.
Hen*_*man 35
1)您的代码不完整.您始终锁定某个(共享)资源.的anyObject应在与该共享对象寿命密切1-1的对应关系.
例如:
a)简单但最直接的模式:
List<MyClass> sharedList = ...;
...
lock (sharedList) { sharedList.Add(item); }
Run Code Online (Sandbox Code Playgroud)
这种模式有一个缺点:如果其他代码也sharedList因其他原因而锁定怎么办?通常不是一个实际问题,但这是推荐模式是(b)的原因:
List<MyClass> sharedList = ...;
private object listLock = new object();
...
lock (listLock) { sharedList.Add(item); }
Run Code Online (Sandbox Code Playgroud)
或者,当共享对象是静态的时(c):
static List<MyClass> sharedList = ...;
private static object listLock = new object();
...
lock (listLock) { sharedList.Add(item); }
Run Code Online (Sandbox Code Playgroud)
2)线程交替设置readerFlag为true或false,因此将输入try/catch块.使用Monitor.Pulse()和.Wait()完成同步.请注意,Wait()将在没有死锁的持续时间内产生锁定.
1:您使用的对象由您尝试强制执行的锁定粒度定义/定义.如果是"任何调用当前实例的东西",那么a private readonly object syncLock = new object()是合理的.如果它是"任何代码,无论实例如何"(特别是静态的),那么private readonly static object syncLock = new object().有时候,有一个明显的"东西"你想保护也将成为:一个列表,队列等,主要错误的决定是:this,typeof(...),任何string,你是拳击每个任何value-type lock,以及任何你已经在实例外泄露了.
2:从当前线程Monitor.Wait 释放锁定,等待"脉冲"或超时,此时它会唤醒并加入队列以重新获得锁定(注意"s"表示重新进入) .这意味着两个线程可以使用a 通过脉冲和等待在它们之间Monitor发出信号.
3:无关; 但基本上"定期检查一个标志,并在脉冲时"