Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Objective-C中初始化并使用threadsafe静态对象_Ios_Objective C_Thread Safety_Grand Central Dispatch - Fatal编程技术网

Ios 在Objective-C中初始化并使用threadsafe静态对象

Ios 在Objective-C中初始化并使用threadsafe静态对象,ios,objective-c,thread-safety,grand-central-dispatch,Ios,Objective C,Thread Safety,Grand Central Dispatch,此方法将从多个线程调用,并返回一个静态字典,调用线程只读取而不写入该字典。初始值是动态的,因此内部实现是NSMutableDictionary 据我所知,由于对dictionary的赋值不是静态初始化器,而且它的状态也发生了进一步的变化,因此在返回@synchronized块之前需要@synchronized块,以确保所有调用线程都能看到初始化的值。这是正确的还是应该删除@synchronized并将内存屏障设置为dispatch_once块的最后一行 我只需要确保最初分配的值对所有调用线程都可

此方法将从多个线程调用,并返回一个静态字典,调用线程只读取而不写入该字典。初始值是动态的,因此内部实现是NSMutableDictionary

据我所知,由于对dictionary的赋值不是静态初始化器,而且它的状态也发生了进一步的变化,因此在返回@synchronized块之前需要@synchronized块,以确保所有调用线程都能看到初始化的值。这是正确的还是应该删除@synchronized并将内存屏障设置为dispatch_once块的最后一行

我只需要确保最初分配的值对所有调用线程都可见

+ (NSDictionary *)threadSafeMethod {
    static NSMutableDictionary *dictionary;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dictionary = [NSMutableDictionary dictionary];
        [dictionary setValue:dynamicValue1 forKey:@"key1"];
        [dictionary setValue:dynamicValue2 forKey:@"key2"];
    });

    @synchronized(dictionary) {
        return dictionary;
    }
}

@synchronized基本上是锁对象上的互斥对象

您使用它的方式只保护对象的返回,而不保护对象的使用。因此,线程将相互阻塞以获取字典指针

更新:由于对象在外部是不可变的,因此不需要保护

我怀疑@synchronize在您的情况下是否有任何用处,请保持原样。初始化将完成一次,其他的将被阻塞,直到第一行完成阻塞。
然后每个人都会得到指向字典的指针,这样所有线程都会读取同一个字典,并且不再有阻塞。

调用者只能读取字典,不能写入字典。我只需要确保初始构造和值对所有调用线程都可见。它还需要在第一次调用该方法时进行惰性初始化,然后在调度运行后基本上不需要同步读取。如果我理解正确,您会担心一个线程进入初始化,而另一个线程在读字典。然后,您会遇到一个问题,即在调度块运行之前,可能有一个线程运行到函数中,您需要在返回时检查nil。如果可能的话,可以在生成线程之前初始化dict?那你根本就不需要同步。不,我知道dispatch_曾经阻止其他呼叫者。但是,即使它完成了,它修改的内存如何对其他线程可见?我找不到任何文件,它强加了记忆障碍。该块不会在线程2中再次运行,但这并不意味着线程2可以在线程1中执行时看到在块中分配的内容。好的,我读取了dispatch once文档。为什么您会担心同步问题?dispatch_once有一些非常聪明的技巧,可以说是非常聪明的技巧,可以在初始化完成后安全地避免障碍。请注意,一些实现是在once.h中内联的