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

场景

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); // 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] 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] -- OSAtomicDecrement64: 1
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] -- OSAtomicDecrement64: 1
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 原子操作

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter(阿斯拉达)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值