多线程编程之原子操作

本文介绍了在Android、iOS及Windows平台上利用CompareAndSwap(CAS)技术进行原子操作的方法,详细展示了不同平台下实现自增、自减及比较交换等操作的具体代码,并解释了这些操作如何帮助提高多线程环境下的效率。
摘要由CSDN通过智能技术生成

  在多线程环境中,对共享的变量的访问,可以使用基于Compare And Swap这种lock free的技术进行实现,这种实现的好处是效率高。

一、原子操作摘录

1.1 Android

  源码:system/core/libcutils /atomic.c(针对X86):

 1 #elif defined(__i386__) || defined(__x86_64__)
 2 
 3 void android_atomic_write(int32_t value, volatile int32_t* addr) {
 4     int32_t oldValue;
 5     do {
 6         oldValue = *addr;
 7     } while (android_atomic_cmpxchg(oldValue, value, addr));
 8 }
 9 
10 int32_t android_atomic_inc(volatile int32_t* addr) {
11     int32_t oldValue;
12     do {
13         oldValue = *addr;
14     } while (android_atomic_cmpxchg(oldValue, oldValue+1, addr));
15     return oldValue;
16 }
17 
18 int32_t android_atomic_dec(volatile int32_t* addr) {
19     int32_t oldValue;
20     do {
21         oldValue = *addr;
22     } while (android_atomic_cmpxchg(oldValue, oldValue-1, addr));
23     return oldValue;
24 }
25 
26 int32_t android_atomic_add(int32_t value, volatile int32_t* addr){
27     int32_t oldValue;
28     do {
29         oldValue = *addr;
30     } while (android_atomic_cmpxchg(oldValue, oldValue+value, addr));
31     return oldValue;
32 }
33 
34 int android_atomic_cmpxchg(int32_t oldvalue, int32_t newvalue, volatile int32_t* addr) {
35     int xchg;
36     asm volatile
37     (
38         " lock; cmpxchg %%ecx, (%%edx);"
39         " setne %%al;"
40         " andl $1, %%eax"
41         : "=a" (xchg)
42         : "a" (oldvalue), "c" (newvalue), "d" (addr)
43     );
44     return xchg;
45 }
View Code

  android_atomic_cmpxchg是使用GNU C嵌入汇编实现,使用X86提供的对CAS的原子支持的指令。oldvalue放在eax寄存器中,newvalue放在ecx中,addr(pointer)放在edx中。cmpxchg指令首先比较addr指向的内存与oldvalue(eax),如果二者相等,将newvalue(ecx)放到addr所指向的内存中,同时设置Z标志1。setne与andl 指令的操作的结果很简单:如果Z标志被设置,则eax为0,否则为1。程序执行最终eax放到xchg变量里。

  可以看出自增、自减操作都是基于android_atomic_cmpxchg实现的,这个操作成功返回1,失败返回0,例如:

int32_t a = 5;
int b = android_atomic_cmpxchg( a, a+1, &a );
printf("%d, %d\n", a, b);        
// 成功时输出:6,1
// 失败时输出:5,0

 1.2 iOS

  头文件:#include <libkern/OSAtomic.h>

Operation

Function name

Description

Add

OSAtomicAdd32
OSAtomicAdd32Barrier
OSAtomicAdd64
OSAtomicAdd64Barrier

Adds two integer values together and stores the result in one of the specified variables.

Increment

OSAtomicIncrement32
OSAtomicIncrement32Barrier
OSAtomicIncrement64
OSAtomicIncrement64Barrier

Increments the specified integer value by 1.

Decrement

OSAtomicDecrement32
OSAtomicDecrement32Barrier
OSAtomicDecrement64
OSAtomicDecrement64Barrier

Decrements the specified integer value by 1.

Logical OR

OSAtomicOr32
OSAtomicOr32Barrier

Performs a logical OR between the specified 32-bit value and a 32-bit mask.

Logical AND

OSAtomicAnd32
OSAtomicAnd32Barrier

Performs a logical AND between the specified 32-bit value and a 32-bit mask.

Logical XOR

OSAtomicXor32
OSAtomicXor32Barrier

Performs a logical XOR between the specified 32-bit value and a 32-bit mask.

Compare and swap

OSAtomicCompareAndSwap32
OSAtomicCompareAndSwap32Barrier
OSAtomicCompareAndSwap64
OSAtomicCompareAndSwap64Barrier
OSAtomicCompareAndSwapPtr
OSAtomicCompareAndSwapPtrBarrier
OSAtomicCompareAndSwapInt
OSAtomicCompareAndSwapIntBarrier
OSAtomicCompareAndSwapLong
OSAtomicCompareAndSwapLongBarrier

Compares a variable against the specified old value. If the two values are equal, this function assigns the specified new value to the variable; otherwise, it does nothing. The comparison and assignment are done as one atomic operation and the function returns a Boolean value indicating whether the swap actually occurred.

Test and set

OSAtomicTestAndSet
OSAtomicTestAndSetBarrier

Tests a bit in the specified variable, sets that bit to 1, and returns the value of the old bit as a Boolean value. Bits are tested according to the formula (0×80 >> (n & 7)) of byte((char*)address + (n >> 3)) where n is the bit number and address is a pointer to the variable. This formula effectively breaks up the variable into 8-bit sized chunks and orders the bits in each chunk in reverse. For example, to test the lowest-order bit (bit 0) of a 32-bit integer, you would actually specify 7 for the bit number; similarly, to test the highest order bit (bit 32), you would specify 24 for the bit number.

Test and clear

OSAtomicTestAndClear
OSAtomicTestAndClearBarrier

Tests a bit in the specified variable, sets that bit to 0, and returns the value of the old bit as a Boolean value. Bits are tested according to the formula (0×80 >> (n & 7)) of byte((char*)address + (n >> 3)) where n is the bit number and address is a pointer to the variable. This formula effectively breaks up the variable into 8-bit sized chunks and orders the bits in each chunk in reverse. For example, to test the lowest-order bit (bit 0) of a 32-bit integer, you would actually specify 7 for the bit number; similarly, to test the highest order bit (bit 32), you would specify 24 for the bit number.

  这些操作中,可能关心的地方就是函数的返回值,这个返回值在编程的时看头文件说明就好了,比较方便。官网文档说明是这样的:The arithmetic operations return the new value, after the operation has been performed.  The boolean operations come in two styles, one of which returns the new value, and one of which (the "Orig" versions) returns the old.  The compare-and-swap operations return true if the comparison was equal, ie if the swap occured.  The bit test and set/clear operations return the original value of the bit.  The dequeue operation returns the most recently enqueued element, or NULL if the list in empty.

1.3 Windows

  Windows平台上的操作其实也是大体类似的,查看InterLockedIncrement、InterLockedDecrement系列的函数就知道了,需要注意的是这两个函数返回操作后的新值,而不是操作前的原始值。

Headerwindows.h
Librarycoredll.lib
Windows Embedded CEWindows CE .NET 4.0 and later
Windows MobileWindows Mobile Version 5.0 and later

转载于:https://www.cnblogs.com/kuliuheng/p/5612553.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值