Objective c 类级静态变量的原子性

Objective c 类级静态变量的原子性,objective-c,static-variables,atomicity,Objective C,Static Variables,Atomicity,我正在使用Objective-C类,该类包含一个静态变量,可以随时存储、检索或释放: 用户.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

我正在使用Objective-C类,该类包含一个静态变量,可以随时存储、检索或释放:

用户.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

我的问题是关于这个静态类级别变量的原子性。声明ivar默认为
strong、readwrite、非原子的
,原子性由getter和setter定义。这也适用于静态变量吗?默认情况下,
currentUser
是非原子的吗?要使
currentUser
原子化,我必须将getter和setter封装在
@synchronized(self){…}
块中?

所有变量都是非原子的

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

对于普通的旧变量,没有任何代码的自动合成使其原子化。如果您需要一个原子变量,那么您需要添加自己的代码以使其访问原子化

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

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


对于您问题中的情况,另一个解决方案是去掉
static
变量,并使用单例设置类。然后单例可以跟踪当前用户。

所有变量都是非原子变量

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

对于普通的旧变量,没有任何代码的自动合成使其原子化。如果您需要一个原子变量,那么您需要添加自己的代码以使其访问原子化

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

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


对于您问题中的情况,另一个解决方案是去掉
static
变量,并使用单例设置类。然后单例可以跟踪当前用户。

@synchronized(self)
从类方法而不是实例方法中工作(因为那里,
self
基本上是指
类而不是实例)?@NSGod将在类方法中工作并与使用
@synchronized结合使用([自我类])
在实例方法中,所有访问都将从任何类/实例方法中同步。有一种情况会失败,即.m文件中的任何C函数也会访问
静态
变量。如果存在子类,也会失败。如果对该类及其子类调用
+currentUser
,则en
self
将是两种不同的东西,访问将不会同步。最安全的将是
@synchronized([User class])
或显式锁。@kenthomass很好。类和子类之间的
[self class]
将不同。将
@synchronized(self)
从类方法而不是实例方法中工作(因为在那里,
self
基本上指的是
类而不是实例)?@NSGod将在类方法中工作,并结合使用
@synchronized([self class])
在实例方法中,所有访问都将从任何类/实例方法中同步。有一种情况会失败,即.m文件中的任何C函数也会访问
静态
变量。如果存在子类,也会失败。如果对该类及其子类调用
+currentUser
,则en
self
将是两种不同的东西,访问将不会同步。最安全的方法是
@synchronized([User class])
或显式锁。@kenthomass很好。类和子类之间的
[self class]
将不同。