程对某些共享的整形变量,都有写操作--只是简单地使用++把变量递增1。这看起来似乎没什么问题,毕竟,还算像是一个原子性操作,但在多数系统中--至少从机器指令的角度来看,C++/CLI执行环境对所有整形类型,并不能普遍地保证无误。
作为示例,例4中的程序有三个线程,每个线程都同时递增一个共享的64位整形变量一千万次,最后显示出这个变量的最终值,从理论上说,应该共递增了三千万次。这个程序目前可以两种方式运行:默认方式使用++操作符以非同步方式运行;而另一种方式,通过带有命令行参数Y或y,这回使用了一个同步的库递增函数。
例4:
using namespace System;
using namespace System::Threading;
static bool interlocked = false;
const int maxCount = 10000000;
/*1*/ static long long value = 0;
void TMain()
{
if (interlocked)
{
for (int i = 1; i <= maxCount; ++i)
{
/*2*/ Interlocked::Increment(value);
}
}
else
{
for (int i = 1; i <= maxCount; ++i)
{
/*3*/ ++value;
}
}
}
int main(array<String^>^ argv)
{
if (argv->Length == 1)
{
if (argv[0]->Equals("Y") || argv[0]->Equals("y"))
{
interlocked = true;
}
}
/*4*/ Thread^ t1 = gcnew Thread(gcnew ThreadStart(&TMain));
Thread^ t2 = gcnew Thread(gcnew ThreadStart(&TMain));
Thread^ t3 = gcnew Thread(gcnew ThreadStart(&TMain));
t1->Start();
t2->Start();
t3->Start();
t1->Join();
t2->Join();
t3->Join();
Console::WriteLine("After {0} operations, value = {1}", 3 * maxCount, value);
}
当使用标准++操作符时,程序5次连续执行之后,输出如插3所示,可看出,结果与正确答案相距甚远,简单估算,大概有17%至50%的递增操作未正确完成;当程序运行于同步方式时--即使用Interlocked::Increment,所有的三千万次递增操作都正常完成,结果计算正确。
插3:
使用++操作符的输出
After 30000000 operations, value = 14323443
After 30000000 operations, value = 24521969
After 30000000 operations, value = 20000000
After 30000000 operations, value = 24245882
After 30000000 operations, value = 25404963
使用Interlocked递增函数的输出
After 30000000 operations, value = 30000000
另外,补充一点,Interlocked类还有另一个decrement函数。 |