好的,首先我必须在免责声明前加上这个问题,我真的很新线程所以这可能是一个'新手'的问题,但我搜索谷歌并找不到答案。据我所知,一个关键部分是可由两个或多个线程访问的代码,一个线程的危险将在另一个完成之前覆盖一个值,反之亦然。您可以对班级以外的变更做些什么,例如,我有一个线路监控程序:
int currentNumber = provider.GetCurrentNumber();
if(provider.CanPassNumber(false, currentNumber))
{
currentNumber++;
provider.SetNumber(currentNumber);
}
在另一个帖子上我有这样的东西:
if(condition)
provider.SetNumber(numberToSet);
现在我担心在第一个函数中我得到currentNumber为5,就在另一个线程之后,数字设置为7然后它重写7到6,忽略设置的线程所做的更改它到7.
无论如何都要锁定provider.SetNumber,直到第一个函数完成?临界区基本上是currentNumber,可以在程序中的许多地方进行更改。
我希望自己明确表示,如果不让我知道,我会更好地解释自己。
编辑: 此外,我的功能非常简短。实际上这个函数要长得多,并且会多次更改currentNumber,所以我真的不想锁定整个函数。如果我锁定每个对provider.SetNumber的调用并在完成后释放它,它可以在它被释放之前更改,然后再将其锁定以调用provider.SetNumber。老实说,我也担心由于性能和死锁而锁定整个函数。
答案 0 :(得分:2)
我建议您查看是否可以使用专为小型操作设计的Interlocked类,而不是使用 lock()关键字。它的开销比锁定少得多,实际上可以降低到某些CPU上的单个CPU指令。
答案 1 :(得分:0)
您想查看Lock
关键字。您也可以将本教程发送到Threading in C#。
答案 2 :(得分:0)
菲利普说,锁在这里很有用。 您不仅应该锁定provider.SetNumber(currentNumber),还需要锁定setter所依赖的任何条件。
lock(someObject)
{
if(provider.CanPassNumber(false, currentNumber))
{
currentNumber++;
provider.SetNumber(currentNumber);
}
}
以及
if(condition)
{
lock(someObject)
{
provider.SetNumber(numberToSet);
}
}
如果condition依赖于numberToSet,则应该在整个块周围使用lock语句。另请注意,someObject必须是相同的对象。
答案 3 :(得分:0)
您可以使用lock
语句输入互斥的关键部分。 lock
将使用对象的引用来区分一个关键部分,如果它访问相同的元素,则必须对所有lock
具有相同的引用。
// Define an object which can be locked in your class.
object locker = new object();
// Add around your critical sections the following :
lock (locker) { /* ... */ }
这会将您的代码更改为:
int currentNumber = provider.GetCurrentNumber();
lock (locker)
{
if(provider.CanPassNumber(false, currentNumber))
{
currentNumber++;
provider.SetNumber(currentNumber);
}
}
并且:
if(condition)
{
lock (locker)
{
provider.SetNumber(numberToSet);
}
}
答案 4 :(得分:0)
首先我对线程不太好但是关键部分是你的代码的一部分,一次只能访问我的一个线程而不是相反...
创建关键部分很容易
Lock(this)
{
//Only one thread can run this at a time
}
注意:此应替换为某个内部对象......
答案 5 :(得分:0)
在您的SetNumber方法中,您只需使用锁定语句:
public class MyProvider {
object numberLock = new object();
...
public void SetNumber(int num) {
lock(numberLock) {
// Do Stuff
}
}
}
另请注意,在您的示例中,currentNumber
是一个原语(int),这意味着如果提供者的实际数据成员的值发生更改,则不会覆盖变量的值。