在 Intel MacOSX 上,您可以使用内置的系统原子操作。没有为 32 位或 64 位整数提供原子获取或设置,但您可以使用提供的 CompareAndSwap 构建它。您可能希望在 XCode 文档中搜索各种 OSAtomic 函数。我在下面写了 64 位版本。32 位版本可以使用类似名称的函数来完成。
#include <libkern/OSAtomic.h>
// bool OSAtomicCompareAndSwap64Barrier(int64_t oldValue, int64_t newValue, int64_t *theValue);
void AtomicSet(uint64_t *target, uint64_t new_value)
{
while (true)
{
uint64_t old_value = *target;
if (OSAtomicCompareAndSwap64Barrier(old_value, new_value, target)) return;
}
}
uint64_t AtomicGet(uint64_t *target)
{
while (true)
{
int64 value = *target;
if (OSAtomicCompareAndSwap64Barrier(value, value, target)) return value;
}
}
请注意,Apple 的 OSAtomicCompareAndSwap 函数以原子方式执行操作:
if (*theValue != oldValue) return false;
*theValue = newValue;
return true;
我们在上面的示例中使用它来创建一个 Set 方法,首先获取旧值,然后尝试交换目标内存的值。如果交换成功,则表明内存的值仍然是交换时的旧值,并且在交换期间被赋予了新值(它本身是原子的),所以我们完成了。如果它没有成功,那么当我们抓取它和尝试重置它时,其他一些线程通过修改中间值进行了干扰。如果发生这种情况,我们可以简单地循环并重试,而代价很小。
Get 方法背后的想法是我们可以首先获取值(如果另一个线程正在干扰,它可能是也可能不是实际值)。然后我们可以尝试将值与自身交换,简单地检查初始抓取是否等于原子值。
我没有根据我的编译器检查这个,所以请原谅任何错别字。
您特别提到了 OSX,但如果您需要在其他平台上工作,Windows 有许多 Interlocked* 功能,您可以在 MSDN 文档中搜索它们。其中一些适用于 Windows 2000 Pro 及更高版本,而一些(尤其是一些 64 位功能)是 Vista 中的新功能。在其他平台上,GCC 4.1 及更高版本具有多种 __sync* 函数,例如 __sync_fetch_and_add()。对于其他系统,您可能需要使用汇编,您可以在 src/system/libroot/os/arch 中找到 HaikuOS 项目的 SVN 浏览器中的一些实现。