【问题标题】:Under what circumstances are atomic properties useful?原子属性在什么情况下有用?
【发布时间】:2011-06-09 10:02:18
【问题描述】:

Objective-C 属性默认为atomic,这确保访问器是原子的,但不能确保整体线程安全(根据this question)。我的问题是,在大多数并发场景中,原子属性不是多余的吗?例如:

场景 1:可变属性

@interface ScaryMutableObject : NSObject {}

@property (atomic, readwrite) NSMutableArray *stuff;

@end

void doStuffWith(ScaryMutableObject *obj) {
    [_someLock lock];
    [obj.stuff addObject:something]; //the atomic getter is completely redundant and could hurt performance
    [_someLock unlock];
}

//or, alternatively
void doStuffWith(ScaryMutableObject *obj) {
    NSMutableArray *cachedStuff = obj.stuff; //the atomic getter isn't redundant
    [_someLock lock];
    [cachedStuff addObject:something]; //but is this any more performant than using a nonatomic accessor within the lock?
    [_someLock unlock];   
}

场景 2:不可变属性

我在想,在使用不可变对象时,原子属性可能有助于避免锁定,但由于不可变对象可以指向 Objective-C 中的可变对象,所以这并没有太大帮助:

@interface SlightlySaferObject : NSObject {}

@property (atomic, readwrite) NSArray *stuff;

@end

void doStuffWith(SlightlySaferObject *obj) {
    [[obj.stuff objectAtIndex:0] mutateLikeCrazy];//not at all thread-safe without a lock
}

我能想到在没有锁的情况下使用原子访问器是安全的(因此完全值得使用原子属性)的唯一场景是:

  1. 使用以下属性 原语;
  2. 使用以下属性 保证是不可变的而不是 指向可变对象(例如 NSStringNSArray 的 不可变对象)。

我错过了什么吗?还有其他使用原子属性的好理由吗?

【问题讨论】:

  • 我认为帖子链接的另一个 SO 问题很好地涵盖了它。 atomic 仅涵盖对属性的 access ——例如您无法取回半旧半新的 int,它会是全新的或全新的(在 obj-c 的情况下,它还可以保证保留计数)。通常,可能需要全锁/屏障。但是,原子访问(不是 CAS,这是不同的)可以在一些“无锁”算法和/或 just-get-me-out 线程循环中使用。所以是的,它们覆盖的范围有限。
  • @pst 完全正确,一些 ABI 上的一些标量类型可能是部分的。我认为 PPC 会将特定标量类型的一半放在寄存器中,另一半放在堆栈中,这样您实际上可以在其他单值标量上获得一半新一半旧的行为!

标签: iphone objective-c multithreading cocoa properties


【解决方案1】:

你没有错过任何东西; atomic 的用处很大程度上仅限于需要从多个线程访问或设置特定值的情况该值也是整数

除了单个值,atomic 不能用于线程安全目的。

我在weblog post a while ago 中写了很多关于它的内容。

这个问题也是What's the difference between the atomic and nonatomic attributes?的[非常好的]重复

【讨论】:

  • 抱歉 3 年后重新启动一个线程,但是@bbum,你的意思是“值不是整数的地方”,因为原子性不能保证你是哪个值,只是一个合法的值?我试图理解这些东西,所以只是要求我澄清一下。
  • @MoMo 对。原子性只是保证价值的完整性,而不是你是否会得到新的或旧的价值。甚至“超越单一价值”这句话有时也是不正确的。在 PPC 上,64 位值有时会在 32 位寄存器和 32 位堆栈条目之间拆分。
猜你喜欢
  • 2011-05-27
  • 2019-01-09
  • 2019-10-03
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 2011-03-28
相关资源
最近更新 更多