非阻塞同步是一种避免锁带来消耗的操作方式。尽管锁是作为同步两个线程有效办法,在大多数情况下获取的耗费是相当大的。对比之下,许多原子操作仅仅需要一小部分时间就能完成,而且还和锁一样有效。

原子在32位或者64为值做数学或者逻辑操作是非常简单的。这些操作依赖于特殊的硬件指令(内存屏障)来确保给定的操作在访问它之前完成。在多线程情况下,我们应该使用包含内存屏障的原子操作来确保内存在线程之间能够正确的同步。

下表列出了在处理数学和逻辑操作时的原子和相应的函数名称。这些函数都在OSAtomic.h中声明,下表中64位版本函数仅在64位进程中可用,同时提供了使用内存屏障版本。(在翻译时Xcode版本这些函数已经DEPRECATED了)

操作 函数名 描述
Add(加) OSAtomicAdd32(OSAtomicAdd32Barrier)、OSAtomicAdd64(OSAtomicAdd64Barrier) 将两个整形值相加,然后把结果存在制定变量中。
Increment(增量) OSAtomicIncrement32(OSAtomicIncrement32Barrier)、OSAtomicIncrement64(OSAtomicIncrement64Barrier) 将指定的整形数据加1
Decrement(减) OSAtomicDecrement32(OSAtomicDecrement32Barrier)、OSAtomicDecrement64(OSAtomicDecrement64Barrier) 将指定的整形数据减1
Logical OR(逻辑或) OSAtomicOr32、OSAtomicOr32Barrier 在指定的32位值和32位掩码之间执行逻辑或运算。
Logical AND(逻辑与) OSAtomicAnd32、OSAtomicAnd32Barrier 在指定的32位值和32位掩码之间执逻辑与运算
Logical XOR(逻辑异或) OSAtomicXor32、OSAtomicXor32Barrier 在指定的32位值和32位掩码之间执逻辑异或运算。
Compare and swap(比较和交换) OSAtomicCompareAndSwap32(OSAtomicCompareAndSwap32Barrier)、OSAtomicCompareAndSwap64(OSAtomicCompareAndSwap64Barrier)、OSAtomicCompareAndSwapPtr(OSAtomicCompareAndSwapPtrBarrier)、OSAtomicCompareAndSwapInt(OSAtomicCompareAndSwapIntBarrier)、OSAtomicCompareAndSwapLong(OSAtomicCompareAndSwapLongBarrier) 将一个变量(变量a)的值和旧值(old-Value)作比较,如果两个值相等,那么该函数将一个指定的值(new-Value)赋值给变量(a = new-Value),否则什么都不做。该函数作为原子操作会返回一个Boolean值,用来指导是否发生了交换。
Test and set(测试和设置) OSAtomicTestAndSet、OSAtomicTestAndSetBarrier (0x80>>(n&7))(根据这个公式算值),((char*)theAddress + (n>>3))(对该地址赋值,加号是指针地址移位)
Test and clear(测试和清除) OSAtomicTestAndClear、OSAtomicTestAndClearBarrier 和上面相同的公式,如果该地址上的值不为空则清空,返回值为是否清除了相关数据。

大多数原子操作的函数都能够从函数名看出来是做什么的。下面会展示相关函数的使用(但是这些函数在我实践的时候是过时了的,所以就直接搬官方文档的代码了)。

/// 官方文档例子
int32_t  theValue = 0;
OSAtomicTestAndSet(0, &theValue);
// theValue is now 128.

theValue = 0;
OSAtomicTestAndSet(7, &theValue);
// theValue is now 1.

theValue = 0;
OSAtomicTestAndSet(15, &theValue)
// theValue is now 256.

OSAtomicCompareAndSwap32(256, 512, &theValue);
// theValue is now 512.

OSAtomicCompareAndSwap32(256, 1024, &theValue);
// theValue is still 512

本人总结TIPS

  • 使用原子操作的场合:原子在32位或者64为值做数学或者逻辑操作是非常简单的;

results matching ""

    No results matching ""