gpt4 book ai didi

ios - 使一个简单的 NSInteger 计数器线程安全

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:33:15 25 4
gpt4 key购买 nike

我定义了一个 NSInteger 计数器 并在回调中更新了它的值,如下面的代码所示(回调在另一个线程中):

-(void) myFunc {
NSLog(@"initialise counter...");
// I try to use volatile to make it thread safe
__block volatile NSInteger counter = 0;

[self addObserver:myObserver withCallback:^{
// this is in another thread
counter += 1;
NSLog(@"counter = %d", counter);
}];
}

我使用 volatile 关键字使 counter 线程安全,它在属于另一个线程的回调 block 中访问。

当我调用 myFunc 两次时:

// 1st time call
[self myFunc];
// 2nd time call
[self myFunc];

输出是这样的:

initialise counter...
counter = 1;
counter = 2;
counter = 3;
counter = 4;
counter = 1; // weird
initialise counter...
counter = 2; // weird
counter = 3;
counter = 1; // weird
counter = 4;

看起来第二次调用产生了一个初始值错误的计数器,counter=4 之前的输出是 counter=1,这也很奇怪。

是不是因为我的代码即使使用 volatile 关键字也不是线程安全的?如果是这样,如何使我的计数器线程安全?如果它是线程安全的,为什么我会得到奇怪的输出?

最佳答案

对于原子计数器的简单情况,GCD 就有点过分了。使用 OSAtomic 函数:

-(void) myFunc {
static int64_t counter;

[self addObserver:myObserver withCallback:^{
// this is in another thread
int64_t my_value = OSAtomicIncrement64Barrier(&counter);
NSLog(@"counter = %d", my_value);
}];
}

请注意,代码记录的是增量函数的结果,而不是静态变量。结果为您提供特定操作的原子结果。使用静态变量将为您提供计数器的快照,该快照对于您的增量操作而言不是原子的。

关于ios - 使一个简单的 NSInteger 计数器线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37990290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com