类级静态变量的原子性

时间:2016-05-06 16:31:09

标签: objective-c static-variables atomicity

我正在使用一个Objective-C类,它包含一个可以随时存储,检索或取消分配的静态变量:

User.h

@interface User : NSObject

/// Returns the current user if set, nil if not
+ (User * _Nullable)currentUser;

/// Sets the current user
+ (void)setCurrentUser:(NSString * _Nonnull)name;

/// Removes the current user
+ (void)removeCurrentUser;

// Getters

/// Returns the user's name if set, nil if there is no user set
@property (nullable, nonatomic, strong, readonly) NSString *name;

@end

User.m

@interface User ()

@property (nullable, nonatomic, strong, readwrite) NSString *name;

@end

@implementation User

#pragma mark - Static Variables

static User *currentUser;

#pragma mark - Static Object Setters and Getters

+ (User *)currentUser
{
    return currentUser;
}

+ (void)setCurrentUser:(NSString * _Nonnull)name
{
    currentUser = [[User alloc] initWithName:name];
}

+ (void)removeCurrentUser
{
    currentUser = nil;
}

#pragma mark - init

- (instancetype)initWithName:(NSString * _Nonnull)name
{
    self = [super init];
    if (self) {
        _name = name;
    }
    return self;
}

@end

我的问题是关于这个静态类级变量的原子性。 This question表示ivars默认为strong, readwrite, nonatomic,并且原子性由getter和setter定义。这也适用于静态变量吗?默认情况下currentUser是非原子的吗?为了使currentUser原子,我必须在@synchronized(self) { ... }块中包装我的getter和setter吗?

1 个答案:

答案 0 :(得分:4)

所有变量都是非原子的。

当一个属性被声明为原子时,setter和getter的合成代码包含额外的代码,以使变量的访问成为原子。

使用普通的旧变量,没有任何代码的自动合成使它们成为原子。如果您需要一个原子变量,您需要添加自己的代码以使其访问原子。

使用@synchronized是一种选择。但是对于static变量,使用@synchronized(self)将不起作用,因为类的多个实例可以访问static变量而@synchronized(self)只会确保没有来自同一个变量的两个线程实例将访问静态但不会阻止另一个线程上的另一个实例也访问static变量。

static的一个解决方案是使用@synchronized([self class])

问题的另一个解决方案是摆脱static变量并使用单例设置类。然后单身人士可以跟踪当前用户。