场景
1.原子操作一般用在多线程执行的逻辑里, 比如统计业务个数 ++count, 或者下载文件个数,下载大小, 设置对象状态等. 如果不用原子操作, 那么可能在并发情况下, 原本的事务指令A会被事务指令2抢占而导致出现数据被覆盖.
说明
1.macOS下提供了 <libkern/OSAtomic.h> 来处理 C 方式的原子操作. 如果是object-c方式的原子属性可以使用关键字 atomic.
2.C++11(vs2012以上)也提供了方便使用可移植的 Atomic Library,
例子
#include <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#include <time.h>
#include <vector>
#include <atomic>
#include <algorithm>
#include <pthread.h>
#include <libkern/OSAtomic.h>
void TestAtomic(){
NSLog(@
"TestAtomic");
volatile int64_t foo =
1;
NSLog(@
"foo is %lld",foo);
OSAtomicIncrement64(&foo);
NSLog(@
"++ OSAtomicIncrement64: %lld",foo);
OSAtomicDecrement64(&foo);
NSLog(@
"-- OSAtomicDecrement64: %lld",foo);
OSAtomicCompareAndSwap64(foo,
64, &foo);
NSLog(@
"= OSAtomicCompareAndSwap64: %lld",foo);
OSAtomicAdd64(
36, &foo);
NSLog(@
"+= OSAtomicAdd64: %lld",foo);
OSAtomicAdd64(-
36, &foo);
NSLog(@
"-= OSAtomicAdd64: %lld",foo);
}
void TestCppAtomicLibrary(){
NSLog(@
"TestCppAtomicLibrary");
std::atomic<int64_t> foo(
1);
NSLog(@
"foo is %lld",foo
.load());
++foo;
NSLog(@
"++ OSAtomicIncrement64: %lld",foo
.load());
--foo;
NSLog(@
"-- OSAtomicDecrement64: %lld",foo
.load());
foo =
64;
NSLog(@
"= OSAtomicCompareAndSwap64: %lld",foo
.load());
foo+=
36;
NSLog(@
"+= OSAtomicAdd64: %lld",foo
.load());
foo-=
36;
NSLog(@
"-= OSAtomicAdd64: %lld",foo
.load());
}
#define THREAD_COUNT 100
#define FOR_NUMBER 10000
static volatile int32_t count =
0;
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static volatile int64_t foo =
1;
static std::atomic<int64_t> foo1(
1);
void* RunCAtomic(
void*){
for(
int i =
0; i< FOR_NUMBER;++i){
OSAtomicIncrement64(&foo);
OSAtomicAdd64(
36, &foo);
}
for(
int i =
0; i< FOR_NUMBER;++i){
OSAtomicDecrement64(&foo);
OSAtomicAdd64(-
36, &foo);
}
OSAtomicIncrement32(&count);
if(OSAtomicCompareAndSwap32(THREAD_COUNT,
0, &count)){
assert(count ==
0);
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
void* RunCppAtomic(
void*){
for(
int i =
0; i< FOR_NUMBER;++i){
++foo1;
foo1+=
36;
}
for(
int i =
0; i< FOR_NUMBER;++i){
--foo1;
foo1-=
36;
}
OSAtomicIncrement32(&count);
if(OSAtomicCompareAndSwap32(THREAD_COUNT,
0, &count)){
assert(count ==
0);
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(
int argc,
const char * argv[])
{
NSAutoreleasePool* pool = [
NSAutoreleasePool new];
TestAtomic();
TestCppAtomicLibrary();
pthread_mutex_init(&mutex,
NULL);
pthread_cond_init(&cond,
NULL);
pthread_attr_t att;
pthread_attr_init(&att);
pthread_attr_setdetachstate(&att, PTHREAD_CREATE_JOINABLE);
NSLog(@
"Begin CAtomic");
for(
int i =
0; i < THREAD_COUNT;++i){
pthread_t t;
pthread_create(&t,&att,RunCAtomic,
NULL);
}
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
assert(foo ==
1);
NSLog(@
"End CAtomic");
NSLog(@
"Begin CppAtomic");
for(
int i =
0; i < THREAD_COUNT;++i){
pthread_t t;
pthread_create(&t,&att,RunCppAtomic,
NULL);
}
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
assert(foo1
.load() ==
1);
NSLog(@
"End CAtomic");
[pool drain];
return 0;
}
输出:
2017-
07-
11 10:
26:
18.162 TestObjc[
744:
303] TestAtomic
2017-
07-
11 10:
26:
18.165 TestObjc[
744:
303] foo
is 1
2017-
07-
11 10:
26:
18.165 TestObjc[
744:
303] ++ OSAtomicIncrement64:
2
2017-
07-
11 10:
26:
18.166 TestObjc[
744:
303]
2017-
07-
11 10:
26:
18.166 TestObjc[
744:
303] = OSAtomicCompareAndSwap64:
64
2017-
07-
11 10:
26:
18.167 TestObjc[
744:
303] += OSAtomicAdd64:
100
2017-
07-
11 10:
26:
18.167 TestObjc[
744:
303] -= OSAtomicAdd64:
64
2017-
07-
11 10:
26:
18.168 TestObjc[
744:
303] TestCppAtomicLibrary
2017-
07-
11 10:
26:
18.168 TestObjc[
744:
303] foo
is 1
2017-
07-
11 10:
26:
18.169 TestObjc[
744:
303] ++ OSAtomicIncrement64:
2
2017-
07-
11 10:
26:
18.169 TestObjc[
744:
303]
2017-
07-
11 10:
26:
18.170 TestObjc[
744:
303] = OSAtomicCompareAndSwap64:
64
2017-
07-
11 10:
26:
18.170 TestObjc[
744:
303] += OSAtomicAdd64:
100
2017-
07-
11 10:
26:
18.171 TestObjc[
744:
303] -= OSAtomicAdd64:
64
2017-
07-
11 10:
26:
18.171 TestObjc[
744:
303]
Begin CAtomic
2017-
07-
11 10:
26:
18.259 TestObjc[
744:
303]
End CAtomic
2017-
07-
11 10:
26:
18.260 TestObjc[
744:
303]
Begin CppAtomic
2017-
07-
11 10:
26:
18.360 TestObjc[
744:
303]
End CAtomic
参考
atomic Windows 原子操作