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

时间:2021-05-19 21:28:25

Is there a way in objective C that I can define a static int that is thread safe?

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

for example if I have class called Session that has:

例如,如果我有一个名为Session的类,它具有:

static unsigned int session_id = 1000;

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

I am constructing session objects from different threads, each session object should have a unique id.

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

4 个解决方案

#1


4  

If you're talking Cocoa, the mutex functionality there is provided by NSLock and NSRecursiveLock.

如果您正在谈论Cocoa,那么NSLock和NSRecursiveLock提供了互斥锁功能。

In order to properly protect non-atomic resource, you need these mutexes, lest multiple threads may try to change the data at the same time (leading to corruption) or use the data in a half-changed state (leading to invalid data).

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

Your code would look something like this:

您的代码看起来像这样:

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;
}

If you're not using Cocoa (or what little Cocoa programming I remember from my brief interlude with an iMac is so dimly remembered that it's near useless), just use the concept, translating it to whatever language or framework you have:

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

  • lock the mutex before using or changing a protected resource.
  • 在使用或更改受保护资源之前锁定互斥锁。

  • use or change the resource.
  • 使用或更改资源。

  • unlock the mutex.
  • 解锁互斥锁。

  • bonus advice 1: lock the mutex as late as possible and unlock it as soon as possible.
  • 奖金建议1:尽可能晚地锁定互斥锁并尽快解锁。

  • bonus advice 2: only lock what you need so you avoid unnecessary delays.
  • 奖金建议2:只锁定你需要的东西,这样可以避免不必要的延误。

Explaining that last point some more: if you synchronise on self for two totally unrelated things (say a session ID and a user ID), they will block each other despite the fact that it's not necessary to do so. I would prefer two separate mutexes to keep the granularity low.

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

Of course, if you only have a mutex on the session ID alone (but see below for caveat), feel free to use synchronized(self) but I'd prefer to do it my way so I wouldn't get caught out adding another protected resource later.

当然,如果你只在会话ID上有一个互斥量(但请参见下面的警告),请随意使用synchronized(self)但我更喜欢按照我的方式去做,所以我不会被抓到添加另一个以后保护资源。

In any case (this is the caveat mentioned), you will probably find that synchronising on self would not adequately protect a static variable, which would be shared across multiple objects. The mutex should belong to the data rather than whatever is using it.

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

#2


9  

I think you're better off using atomic operations to modify session_id. A previous question talks about atomic increment/decrement operations for OS X, and this page talks about the OSAtomic header file. Atomic operations on integers, something that's readily hardware-supported, will probably be substantially faster than using locking constructs.

我认为你最好使用原子操作来修改session_id。前一个问题讨论了OS X的原子递增/递减操作,此页面讨论了OSAtomic头文件。整数上的原子操作,即硬件支持的东西,可能比使用锁定结构快得多。

#3


2  

A response 4 years later presently in iOS8. :o) The best for me is to use a singleton class as follows :

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

You just need to call the method 'generateSessionId' for each new Id value. Using this class to generate your session Ids should be far enough I think.

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

Hope it will help the readers of this post. :o)

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

EDIT

As stated by some readers, the NSInteger 'value' isn't thread safe following this way, only the singleton is.

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

To obtain a complete thread safe 'value' instance variable just change its NSInteger type into NSNumber (to be converted in 'int' with appropriate methods) that is completely thread safe according to Apple's documentation.

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

This may be the simplest and fastest way to get what is desired.

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

#4


1  

There are many options, including (from high-level to low-level) the @synchronized Objective-C directive, NSLock, pthread_mutex_lock, and atomic operations.

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

Read the "Synchronization" section of the Threading Programming Guide for details.

有关详细信息,请阅读“线程编程指南”的“同步”部分。

#1


4  

If you're talking Cocoa, the mutex functionality there is provided by NSLock and NSRecursiveLock.

如果您正在谈论Cocoa,那么NSLock和NSRecursiveLock提供了互斥锁功能。

In order to properly protect non-atomic resource, you need these mutexes, lest multiple threads may try to change the data at the same time (leading to corruption) or use the data in a half-changed state (leading to invalid data).

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

Your code would look something like this:

您的代码看起来像这样:

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;
}

If you're not using Cocoa (or what little Cocoa programming I remember from my brief interlude with an iMac is so dimly remembered that it's near useless), just use the concept, translating it to whatever language or framework you have:

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

  • lock the mutex before using or changing a protected resource.
  • 在使用或更改受保护资源之前锁定互斥锁。

  • use or change the resource.
  • 使用或更改资源。

  • unlock the mutex.
  • 解锁互斥锁。

  • bonus advice 1: lock the mutex as late as possible and unlock it as soon as possible.
  • 奖金建议1:尽可能晚地锁定互斥锁并尽快解锁。

  • bonus advice 2: only lock what you need so you avoid unnecessary delays.
  • 奖金建议2:只锁定你需要的东西,这样可以避免不必要的延误。

Explaining that last point some more: if you synchronise on self for two totally unrelated things (say a session ID and a user ID), they will block each other despite the fact that it's not necessary to do so. I would prefer two separate mutexes to keep the granularity low.

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

Of course, if you only have a mutex on the session ID alone (but see below for caveat), feel free to use synchronized(self) but I'd prefer to do it my way so I wouldn't get caught out adding another protected resource later.

当然,如果你只在会话ID上有一个互斥量(但请参见下面的警告),请随意使用synchronized(self)但我更喜欢按照我的方式去做,所以我不会被抓到添加另一个以后保护资源。

In any case (this is the caveat mentioned), you will probably find that synchronising on self would not adequately protect a static variable, which would be shared across multiple objects. The mutex should belong to the data rather than whatever is using it.

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

#2


9  

I think you're better off using atomic operations to modify session_id. A previous question talks about atomic increment/decrement operations for OS X, and this page talks about the OSAtomic header file. Atomic operations on integers, something that's readily hardware-supported, will probably be substantially faster than using locking constructs.

我认为你最好使用原子操作来修改session_id。前一个问题讨论了OS X的原子递增/递减操作,此页面讨论了OSAtomic头文件。整数上的原子操作,即硬件支持的东西,可能比使用锁定结构快得多。

#3


2  

A response 4 years later presently in iOS8. :o) The best for me is to use a singleton class as follows :

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

You just need to call the method 'generateSessionId' for each new Id value. Using this class to generate your session Ids should be far enough I think.

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

Hope it will help the readers of this post. :o)

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

EDIT

As stated by some readers, the NSInteger 'value' isn't thread safe following this way, only the singleton is.

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

To obtain a complete thread safe 'value' instance variable just change its NSInteger type into NSNumber (to be converted in 'int' with appropriate methods) that is completely thread safe according to Apple's documentation.

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

This may be the simplest and fastest way to get what is desired.

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

#4


1  

There are many options, including (from high-level to low-level) the @synchronized Objective-C directive, NSLock, pthread_mutex_lock, and atomic operations.

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

Read the "Synchronization" section of the Threading Programming Guide for details.

有关详细信息,请阅读“线程编程指南”的“同步”部分。