Programming Languages Hacks

Importanti regole per linguaggi di programmazione rilevanti come Java, C, C++, C#…

  • Subscribe

  • Lettori

    I miei lettori abituali

  • Twitter

Quando usare String.Intern: i Lock

Posted by Ricibald on April 16th, 2009

String è un tipo immutabile che si basa sul pattern Flyweight: ogni volta creiamo una nuova stringa questa prenderà l’istanza memorizzata per quel valore. Un esempio pratico chiarisce tutto:

string s1 = "ciao";    // puntatore: p1
string s2 = "a tutti"; // puntatore: p2
string s3 = s1 + s2;  // puntatore: p3
string s4 = "ciao a tutti"; // puntatore: p3
s1 = s1 + s2; // puntatore: p1
s1 == s3; // true (verosimiglianza dall'override dell'operatore)
(object)s1 == (object)s3;  // false (confronto puntatori)
s1 = String.Inner(s1); // puntatore: p3
(object)s1 == (object)s3;  // true (confronto puntatori)

Questo per dare una spolveratina ai concetti. Il metodo String.Intern consente quindi di restituire il valore del puntatore memorizzato in cache. Ma a cosa può essere utile questa funzione?

Un utilizzo immediato risiede in ragioni di performance: confrontare puntatori è molto più efficiente che confrontare il contenuto. Avere quindi una collezione di stringhe con puntatori intern consente una comparazione molto più efficiente. Normalmente infatti l’approccio in una comparazione dovrebbe essere: per primo confronta i puntatori, altrimenti il contenuto.

Ma esiste un ulteriore utilizzo. Un utilizzo possibile sta nel lock: le funzioni di lock di .NET si basano infatti sul valore del puntatore per effettuare un lock. Immaginiamo quindi un lock di questo tipo:

lock((string)Session["username"]) {
    dbOperation1();
    dbOperation2();
}

Questo lock è sbagliato: infatti se lo stesso utente è collegato da un altro browser il lock potrebbe non essere acquisito. Il seguente metodo consente invece un lock corretto:

lock(String.Intern((string)Session["username"])) {
    dbOperation1();
    dbOperation2();
}

Si noti che questo approccio presuppone l’utilizzo di un unico web server. Se invece abbiamo in cluster differenti server, a seconda del server scelto potremmo avere differenti valori per il puntatore di “username” e l’approccio non sarebbe valido comunque.

Leave a Reply

You must be logged in to post a comment.