Objective c 类级静态变量的原子性
我正在使用Objective-C类,该类包含一个静态变量,可以随时存储、检索或释放: 用户.hObjective 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
@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
,则enself
将是两种不同的东西,访问将不会同步。最安全的将是@synchronized([User class])
或显式锁。@kenthomass很好。类和子类之间的[self class]
将不同。将@synchronized(self)
从类方法而不是实例方法中工作(因为在那里,self
基本上指的是类而不是实例)?@NSGod将在类方法中工作,并结合使用@synchronized([self class])
在实例方法中,所有访问都将从任何类/实例方法中同步。有一种情况会失败,即.m文件中的任何C函数也会访问静态
变量。如果存在子类,也会失败。如果对该类及其子类调用+currentUser
,则enself
将是两种不同的东西,访问将不会同步。最安全的方法是@synchronized([User class])
或显式锁。@kenthomass很好。类和子类之间的[self class]
将不同。