使用ARC:如何实现自定义原子属性?

时间:2015-12-15 09:44:17

标签: objective-c multithreading automatic-ref-counting atomic synthesize

ARC 中,我想要一个用于多线程访问的原子属性:

@interface MyClass
@property (atomic, strong) NSString *myString;
@end

我还想要一个自定义的setter和getter,原因有多种,比如调试或跟踪。

解决方案A,我覆盖了setter和getter:

@implementation MyClass
@synthesize myString = _myString;
static int i;
- (void)setMyString:(NSString *)myString
{
    _myString = myString;
    NSLog(@"%d", i++);
}
- (NSString *)myString
{
    return _myString;
}
@end

解决方案B,我将类接口扩展为具有不同的合成属性:

@interface MyClass ()
@property (atomic, strong) NSString *myPrivateString;
@end

@implementation MyClass
@synthesize myPrivateString = _myPrivateString;
static int i;
- (void)setMyString:(NSString *)myString
{
    _myPrivateString = myString;
    NSLog(@"%d", i++);
}
- (NSString *)myString
{
    return _myPrivateString;
}
@end

解决方案A原子?解决方案B原子?如果它们都不是原子的,我应该使用objc_setProperty and objc_getProperty,还是应该使用@synchronized(self),还是有更好的锁定机制来避免锁定自己?

(子问题:如果是B,直接获取或设置_myPrivateString与获取或设置self.myPrivateString或不安全一样安全吗?)

2 个答案:

答案 0 :(得分:1)

  

解决方案是原子?

不,不是。在提供getter / setter方法的自定义版本时,您还需要提供锁定机制。使用@synchronized(self)将起作用,但是如果此属性存在高争用,则可能需要为每个属性创建一个锁定对象。但是,这不太可能。

  

解决方案B是原子的吗?

是的,但是确保使用self.myPrivateString = myString;来确保您访问实现锁定的getter / setter方法。

我建议使用解决方案A,因为它很简单,总是很好。

答案 1 :(得分:0)

因为您使用的是没有前导下划线的实例变量,所以您已陷入实际访问实例变量而非访问器方法的陷阱。当您访问实例变量时," atomic"不会做任何事情"为了你。任何具有任何Objective-C经验的人都会非常非常强烈地建议您不要使用没有前导下划线的实例变量。只需删除@synthesize(所以你自己构建了一个陷阱,落入它,你实际上做了额外的工作)。

所以你的解决方案都没有任何原子性。