我正在尝试追踪我认为可能与多线程应用程序相关的错误。我简化了下面的代码:
class Outer {
private static int count;
//this function is called from multiple threads in quick succession
public void DoFoo() {
Inner.Increment(ref count);
}
}
class Inner {
private readonly static object mLock = new object();
public static string Increment(ref count) {
lock (mLock) (
if (count > 1000)
count = 0;
count++;
}
return count.ToString();
}
}
锁定能否保证以这种方式传递的变量的安全性?是否有任何复制计数似乎不明显,可能会打破内存安全?我以为它可能会返回一个新的int并在方法结束时进行赋值。除此之外,我的理解是锁定部分将处理任何缓存问题。
引起我们注意的错误似乎是其中一个线程有一个陈旧版本的计数。
答案 0 :(得分:2)
这里的问题是,当某个其他线程为== 0时,可以直接读取>>> a = { "system1": "Service 1", "System2": "Service2" }
>>> b = json.loads(a)
>>> b
{u'system1': u'Service 1', u'System2': u'Service2'}
,因为您可以在没有获得锁定的情况下访问b['system1']
(通常在您的代码中写入,{ {1}}只能在第一次调用Outer.count
之前为0,从那时起它只能有1到1001之间的值。
无锁可以这样做:
Outer.count
我计算count
值并使用它(通过Inner.Increment
)只有class Inner
{
public static string Increment(ref int count)
{
while (true)
{
int original = count;
int next = original;
if (next > 1000)
{
next = 0;
}
next++;
if (Interlocked.CompareExchange(ref count, next, original) == original)
{
return next.ToString();
}
}
}
}
在此期间未发生变化。