线程安全的静态变量目标c

时间:2010-10-28 02:17:41

标签: objective-c thread-safety

在目标C中是否有一种方法可以定义一个线程安全的静态int?

例如,如果我有名为Session的类,那么:

static unsigned int session_id = 1000;

- (int) generateSessionID{
        return session_id++;
}

我正在构建来自不同线程的会话对象,每个会话对象 应该有一个唯一的ID。

4 个答案:

答案 0 :(得分:9)

我认为您最好使用atomic operations来修改session_id。 A previous question讨论OS X的原子递增/递减操作,this page讨论OSAtomic头文件。整数上的原子操作,很容易得到硬件支持,可能比使用锁定结构要快得多。

答案 1 :(得分:5)

如果您正在谈论Cocoa,那么NSLockNSRecursiveLock会提供互斥功能。

为了正确保护非原子资源,您需要这些互斥锁,以免多个线程可能同时尝试更改数据(导致损坏)或使用处于半更改状态的数据(导致无效)数据)。

您的代码看起来像这样:

static NSLock session_id_lock;
static unsigned int session_id = 1000;

- (int) generateSessionID{
    int new_id;
    [myLock lock];
    new_id = session_id++;
    [myLock unlock];
    return new_id;
}

如果你没有使用Cocoa(或者我记得从我对iMac的短暂插曲中记得的那些小Cocoa编程是如此模糊,以至于它几乎无用),只需使用这个概念,将其翻译成你拥有的任何语言或框架:

  • 在使用或更改受保护资源之前锁定互斥锁。
  • 使用或更改资源。
  • 解锁互斥锁。
  • 奖励建议1:尽可能晚地锁定互斥锁并尽快解锁。
  • 奖励建议2:只锁定你需要的东西,这样可以避免不必要的延误。

再解释一下最后一点:如果你在self上同步两个完全不相关的东西(比如一个会话ID和一个用户ID),它们会相互阻塞,尽管它没有必要这样做。我更喜欢使用两个独立的互斥锁来保持较低的粒度。

当然,如果您只在会话ID上使用互斥锁(但请参阅下面的警告),请随时使用synchronized(self),但我更愿意按照自己的方式进行,所以我不会后来发现了添加另一个受保护的资源。

在任何情况下(这都是提到的警告),您可能会发现self上的同步不能充分保护静态变量,静态变量将在多个对象之间共享。互斥锁应该属于数据而不是使用它的任何东西。

答案 2 :(得分:2)

4年后的回应目前在iOS8中。 :O) 对我来说最好的是使用单例类,如下所示:

(yourFile.h)

#import <Foundation/Foundation.h>

@interface singletonSessionId : NSObject

+ (singletonMsgNbr*)sharedSingleton;

- (void)generateSessionId;

@property NSInteger value;

@end

=============================================== ====== (yourFile.m)

#import "singletonSessionId.h"

@implementation singletonSessionId
@synthesize value = _value;

+ (singletonMsgNbr*)sharedSingleton {

    static singletonSessionId *instance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[singletonSessionId alloc]init];
        instance.value = 1000;
    });

    return instance;
}

- (void)generateSessionId {
    _value += 1;
}

@end

您只需要为每个新的Id值调用方法'generateSessionId'。 使用这个类生成你的会话ID应该足够我想了。

希望它能帮助这篇文章的读者。 :O)

修改

正如一些读者所说,NSInteger'值'在这种方式下不是线程安全的,只有单例是。

要获得完整的线程安全'value'实例变量,只需将其NSInteger类型更改为NSNumber (使用适当的方法转换为'int')即<根据Apple的文档,强>完全线程安全

这可能是获得所需内容的最简单,最快捷的方式。

答案 3 :(得分:1)

有许多选项,包括(从高级到低级)@synchronized Objective-C指令,NSLockpthread_mutex_lock和原子操作。

有关详细信息,请阅读Threading Programming Guide的“同步”部分。