在我们的应用程序中,我们在多个位置使用单例,最近我通过并向所有单例方法添加了@synchronized
命令,以确保它们是线程安全的。我的问题是,在调用它之间有什么区别:
+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
@synchronized(receiverCache)
{
if (!receiverCache )
receiverCache = [[RLReceiver alloc] init];
return receiverCache;
}
}
在这种情况下,我同步类RLReceiver
的静态实例,但我也看到了(以及编译器令人惊讶地允许)这个:
+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
@synchronized(self)
{
if (!receiverCache )
receiverCache = [[RLReceiver alloc] init];
return receiverCache;
}
}
同步在self
上的位置。这让我感到困惑,因为这个方法是一个类方法,在这个方法的范围内甚至不应该有self
。任何人都可以了解静态变量和self之间的区别是什么,在这种情况下,甚至在类方法中是否会有自我?
答案 0 :(得分:0)
根据Apple Doc:“传递给@synchronized指令的对象是用于区分受保护块的唯一标识符。如果在两个不同的线程中执行上述方法,则在每个线程上为anObj参数传递不同的对象每个都会锁定并继续处理而不被另一个阻塞。但是,如果在两种情况下都传递相同的对象,则其中一个线程将首先获取锁定,另一个线程将阻塞,直到第一个线程完成关键部分。“
// Apple示例:
- (void)myMethod:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
在你的情况下,Hot Licks如何说问题是第一次发布。您的对象在第一次启动时不存在,并且synchronized无法正常工作。如果您尝试:
[1]
+(RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
@synchronized(receiverCache)
{
if (!receiverCache ) {
receiverCache = [[RLReceiver alloc] init];
}
for (int i=0; i<100; i++) {
NSLog(@"Numbers in order i %i",i);
}
return receiverCache;
}
}
和[2]
+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
@synchronized(self)
{
if (!receiverCache ) {
receiverCache = [[RLReceiver alloc] init];
}
for (int i=0; i<100; i++) {
NSLog(@"Numbers in order i %i",i);
}
return receiverCache;
}
}
从第一次调用的另一个对象:
dispatch_async(dispatch_queue_create("OtherQueue", 0), ^{
RLReceiver *rece= [RLReceiver getReceiver];
});
RLReceiver *receSorF = [RLReceiver getReceiver];
你可以看到在[1]情况下数字是如何混合和同步不起作用的。在[2]情况下,一个计数等待另一个。
当我们在现有对象中同步代码时,我们可以使用该对象,在其他情况下是类名。
谢谢@HotLicks。