开发者

Thread safe static variables objective c

开发者 https://www.devze.com 2023-01-22 21:46 出处:网络
Is there a way in objective C that I can define a static int that is thread safe? f开发者_开发百科or example if I have class called Session that has:

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

f开发者_开发百科or example if I have class called Session that has:

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.


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.


If you're talking Cocoa, the mutex functionality there is provided by NSLock and 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:

  • 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.
  • bonus advice 2: only lock what you need so you avoid unnecessary delays.

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.

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.

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.


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

(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.

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

EDIT

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

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.

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


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

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

0

精彩评论

暂无评论...
验证码 换一张
取 消