[C/C++]_[macOS-Windows]_[原子操作2]

来源:互联网 发布:中国不成熟的网络环境 编辑:程序博客网 时间:2024/06/10 18:20

场景

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 10000static 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); // fail if ++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] TestAtomic2017-07-11 10:26:18.165 TestObjc[744:303] foo is 12017-07-11 10:26:18.165 TestObjc[744:303] ++ OSAtomicIncrement64: 22017-07-11 10:26:18.166 TestObjc[744:303] -- OSAtomicDecrement64: 12017-07-11 10:26:18.166 TestObjc[744:303] = OSAtomicCompareAndSwap64:  642017-07-11 10:26:18.167 TestObjc[744:303] += OSAtomicAdd64:  1002017-07-11 10:26:18.167 TestObjc[744:303] -= OSAtomicAdd64:  642017-07-11 10:26:18.168 TestObjc[744:303] TestCppAtomicLibrary2017-07-11 10:26:18.168 TestObjc[744:303] foo is 12017-07-11 10:26:18.169 TestObjc[744:303] ++ OSAtomicIncrement64: 22017-07-11 10:26:18.169 TestObjc[744:303] -- OSAtomicDecrement64: 12017-07-11 10:26:18.170 TestObjc[744:303] = OSAtomicCompareAndSwap64:  642017-07-11 10:26:18.170 TestObjc[744:303] += OSAtomicAdd64:  1002017-07-11 10:26:18.171 TestObjc[744:303] -= OSAtomicAdd64:  642017-07-11 10:26:18.171 TestObjc[744:303] Begin CAtomic2017-07-11 10:26:18.259 TestObjc[744:303] End CAtomic2017-07-11 10:26:18.260 TestObjc[744:303] Begin CppAtomic2017-07-11 10:26:18.360 TestObjc[744:303] End CAtomic

参考

atomic
Windows 原子操作

原创粉丝点击