Apple的样本MVCN网络中的Singleton类NetworkManager是否正确?

Bob*_*ell 5 objective-c ios

以下是示例代码的链接http://developer.apple.com/library/ios/#samplecode/MVCNetworking/Introduction/Intro.html

以下是NetworkManager.m文件中的代码段

+ (NetworkManager *)sharedManager
// See comment in header.
{
    static NetworkManager * sNetworkManager;

    // This can be called on any thread, so we synchronise.  We only do this in 
    // the sNetworkManager case because, once sNetworkManager goes non-nil, it can 
    // never go nil again.

    if (sNetworkManager == nil) {
        @synchronized (self) {
            sNetworkManager = [[NetworkManager alloc] init];
            assert(sNetworkManager != nil);
        }
    }
    return sNetworkManager;
}
Run Code Online (Sandbox Code Playgroud)

显然这里存在线程安全问题.当存在多个线程时,可以创建两个NetworkManager实例.所以Apple犯了一个错误,对吗?

Kur*_*vis 1

是的,这是错误的。sNetworkManager从as开始nil,考虑两个线程 T1 和 T2。

一种可能的情况(如果不太可能的话)是:

T1: Determines (sNetworkManager == nil) is true
T2: Determines (sNetworkManager == nil) is true
T1: Takes the @synchronized lock
    Creates a NetworkManager 
    Sets sNetworkManager
    Releases the lock
T2: Takes the @synchronized lock
    Creates a NetworkManager 
    Sets sNetworkManager, LEAKING the first one
    Releases the lock
Run Code Online (Sandbox Code Playgroud)

这个问题有一些更安全的方法。