Domanda

Io sono re-factoring po ' di codice e chiedo circa l'uso di una lock nel costruttore di istanza.

public class MyClass {

    private static Int32 counter = 0;
    private Int32 myCount;

    public MyClass() {

        lock(this) {
            counter++;
            myCount = counter;
        }
    }
}

Si prega di confermare

  1. Costruttori di istanza sono thread-safe.
  2. L'istruzione di blocco impedisce l'accesso a tale blocco di codice, non statico 'contatore' membro.

Se l'intento originale del programmatore sono stati per ogni istanza conoscere la sua 'count', come faccio a sincronizzare l'accesso a il 'contatore' membro per garantire che un altro thread non è nuovo ing un MyClass e la modifica di il conte prima di questo set è conte?

CRONACA - Questa classe non è un singleton.Le istanze devono semplicemente essere consapevoli del loro numero.

È stato utile?

Soluzione

@ajmastrean

Non sto dicendo che si dovrebbe utilizzare il singleton pattern stesso, ma adottare il suo metodo di incapsulamento la creazione di un'istanza di processo.

cioè

  • Rendere il costruttore privato.
  • Creare un'istanza statica metodo che restituisce il tipo.
  • In statico metodo di istanza, utilizzare la parola chiave lock prima di creare un'istanza.
  • Creare una nuova istanza del tipo.
  • Incrementare il numero.
  • Sbloccare e restituire nuova istanza.

MODIFICA

Un problema che si è verificato a me, se tu come fai a sapere quando il conteggio è andato giù?;)

EDIT DI NUOVO

A pensarci, è possibile aggiungere codice per il distruttore che chiama un altro metodo statico per decrementare il contatore :D

Altri suggerimenti

Se si sta incrementando solo un numero, c'è una classe speciale (Connesso) solo che...

http://msdn.microsoft.com/en-us/library/system.threading.interlocked.increment.aspx

Intrecciata.Incremento Metodo

Incrementi una variabile specificata, e memorizza il risultato, come un'operazione atomica.

System.Threading.Interlocked.Increment(myField);

Ulteriori informazioni circa la filettatura migliori pratiche...

http://msdn.microsoft.com/en-us/library/1c9txz50.aspx

Sto indovinando questo è un singleton pattern o qualcosa di simile.Quello che vuoi fare è bloccare il vostro oggetto, ma bloccare il contatore senza modifica.

private static int counter = 0;
private static object counterLock = new Object();

lock(counterLock) {
    counter++;
    myCounter = counter;
}

Perché il codice attuale è una sorta di ridondante.In particolare sta nel costruttore dove c'è un solo filo che può chiamare un costruttore, a differenza dei metodi di dove potrebbe essere condiviso tra thread e sono accessibili da qualsiasi thread che è condivisa.

Dal poco che posso capire dal codice, si sta cercando di dare all'oggetto il conteggio corrente al momento di essere creato.Quindi, con il codice sopra il contatore verrà bloccato mentre il contatore viene aggiornato e configurato in locale.Così tutti gli altri costruttori, si dovrà attendere il contatore per essere rilasciato.

È possibile utilizzare un altro oggetto statico di blocco su di esso.

private static Object lockObj = new Object();

e bloccare questo oggetto nel costruttore.

lock(lockObj){}

Tuttavia, io non sono sicuro se ci sono situazioni che devono essere trattati a causa di ottimizzazione del compilatore in .NET come nel caso di java

Il modo più efficace per fare questo, sarebbe usare il Interbloccate operazione di incremento.Si incrementa il contatore e ritorna il nuovo valore impostato del contatore statico tutto in una volta (atomico)

class MyClass {

    static int _LastInstanceId = 0;
    private readonly int instanceId; 

    public MyClass() { 
        this.instanceId = Interlocked.Increment(ref _LastInstanceId);  
    }
}

Originale esempio, il blocco(questo) dichiarazione di non avere l'effetto desiderato, perché ogni singola istanza avrà un diverso "questo" di riferimento, e più istanze potrebbe quindi essere l'aggiornamento del membro statico allo stesso tempo.

In un certo senso, i costruttori possono essere considerati di essere thread-safe, perché il riferimento all'oggetto costruito non è visibile fino a quando il costruttore ha completato, ma questo non buono per la protezione di una variabile statica.

(Mike Schall aveva intrecciati po ' prima)

Penso che se si modifica il Singleton Pattern per includere un conteggio (ovviamente utilizzando il metodo thread-safe), che andrà bene :)

Modifica

Merda ho accidentalmente cancellato!

Io non sono sicuro se i costruttori di istanza SONO thread-safe, ricordo di aver letto su questo in un design pattern libro, è necessario assicurarsi che le serrature sono in posizione durante il processo di creazione di un'istanza, esclusivamente a causa di questo..

@Rob

Cordiali saluti, Questa classe non può essere un singleton, ho bisogno di accedere a istanze diverse.Si deve semplicemente mantenere un conteggio.Qual è la parte che il singleton pattern vuoi cambiare per eseguire il 'contatore' incremento?

O stai suggerendo che esporre un metodo statico per la costruzione di bloccare l'accesso al codice che incrementi e legge il contatore con un lucchetto.

public MyClass {

    private static Int32 counter = 0;
    public static MyClass GetAnInstance() {

        lock(MyClass) {
            counter++;
            return new MyClass();
        }
    }

    private Int32 myCount;
    private MyClass() {
        myCount = counter;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top