9 Stimmen

Gewindesichere statische Variablen objective c

Gibt es eine Möglichkeit in Objective C, dass ich eine statische int definieren kann, die Thread sicher ist?

Wenn ich zum Beispiel eine Klasse namens Session habe, die über:

static unsigned int session_id = 1000;

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

Ich konstruiere Sitzungsobjekte aus verschiedenen Threads, jedes Sitzungsobjekt sollte eine eindeutige ID haben.

9voto

Wyatt Anderson Punkte 9258

Ich denke, es ist besser, wenn Sie atomare Operationen zu ändern session_id . A vorherige Frage spricht über atomare Inkrement-/Dekrement-Operationen für OS X, und diese Seite spricht über die OSAtomic Header-Datei. Atomare Operationen auf Ganzzahlen, etwas, das von der Hardware leicht unterstützt wird, wird wahrscheinlich wesentlich schneller sein als die Verwendung von Sperrkonstrukten.

7voto

paxdiablo Punkte 809679

Wenn Sie über Cocoa sprechen, wird die Mutex-Funktionalität dort von NSLock y NSRecursiveLock .

Um nicht-atomare Ressourcen ordnungsgemäß zu schützen, benötigen Sie diese Mutexe, damit nicht mehrere Threads gleichzeitig versuchen, die Daten zu ändern (was zu Korruption führt) oder die Daten in einem halbgeänderten Zustand zu verwenden (was zu ungültigen Daten führt).

Ihr Code würde etwa so aussehen:

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

Wenn Sie kein Cocoa verwenden (oder das bisschen Cocoa-Programmierung, an das ich mich von meinem kurzen Zwischenspiel mit einem iMac erinnere, ist so schwach, dass es fast nutzlos ist), verwenden Sie einfach das Konzept und übersetzen Sie es in eine beliebige Sprache oder ein beliebiges Framework, das Sie haben:

  • sperren Sie den Mutex, bevor Sie eine geschützte Ressource verwenden oder ändern.
  • die Ressource zu nutzen oder zu verändern.
  • den Mutex entsperren.
  • Bonustipp 1: Sperren Sie den Mutex so spät wie möglich und heben Sie ihn so bald wie möglich wieder auf.
  • Bonustipp 2: Schließen Sie nur ab, was Sie brauchen, um unnötige Verzögerungen zu vermeiden.

Um den letzten Punkt weiter zu erläutern: Wenn Sie die Synchronisierung auf self für zwei völlig unverbundene Dinge (z. B. eine Sitzungs-ID und eine Benutzer-ID), blockieren sie sich gegenseitig, obwohl dies nicht notwendig ist. Ich würde zwei separate Mutexe bevorzugen, um die Granularität niedrig zu halten.

Wenn Sie natürlich nur eine Mutex auf die Sitzungs-ID allein haben (aber siehe unten), können Sie auch synchronized(self) aber ich würde es lieber auf meine Art machen, damit ich nicht später eine weitere geschützte Ressource hinzufügen muss.

In jedem Fall (dies ist der erwähnte Vorbehalt) werden Sie wahrscheinlich feststellen, dass die Synchronisierung auf self würde eine statische Variable, die von mehreren Objekten gemeinsam genutzt wird, nicht ausreichend schützen. Der Mutex sollte zum Daten als derjenige, der es verwendet.

2voto

XLE_22 Punkte 4492

Eine Antwort 4 Jahre später, jetzt in iOS8 :o) Das Beste für mich ist, eine Singleton-Klasse wie folgt zu verwenden:

(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

Sie müssen lediglich die Methode "generateSessionId" für jeden neuen Id-Wert aufrufen. Die Verwendung dieser Klasse zur Erzeugung Ihrer Sitzungskennungen sollte meiner Meinung nach ausreichen.

Ich hoffe, es wird den Lesern dieses Beitrags helfen :o)

EDIT

Wie von einigen Lesern erwähnt, ist der NSInteger-'Wert' auf diese Weise nicht thread-sicher, sondern nur das Singleton.

Um eine vollständig thread-sichere Instanzvariable 'value' zu erhalten, genügt es seinen NSInteger-Typ in NSNumber ändern (mit geeigneten Methoden in 'int' zu konvertieren) das ist vollständig fadensicher laut der Apple-Dokumentation.

Dies kann der einfachste und schnellste Weg sein, um das Gewünschte zu erreichen.

1voto

David Gelhar Punkte 27707

Es gibt viele Optionen, darunter (von der höchsten zur niedrigsten Ebene) die @synchronized Objective-C-Anweisung, NSLock , pthread_mutex_lock und atomare Operationen.

Lesen Sie den Abschnitt "Synchronisierung" in der Leitfaden zur Programmierung von Threads für Einzelheiten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X