• Català
  • Castellano
  • English


Sincronitzant l'Execució de Processos


L'Objective-C suporta multiprocessos en les aplicacions. Això significa que dos processos poden intentar modificar el mateix objecte a l'hora, una situació que pot causar problemes seriosos en un programa. Per protegir seccions de codi que serà executat per més d'un procés a l'hora, l'Objective-C proporcions la directiva @synchronized().

La directiva @synchronized() bloqueja una secció de codi per que només l'utilitzi un únic procés. altres processos estaran bloquejats fins que el procés surti del codi protegit; així, quan l'execució continua passada l'última instrucció en el block @synchronized().

La directiva @synchronized() agafa com a únic argument qualsevol objecte Objective-C, inclòs self. Aquest objecte es coneix com a semàfor d'exclusió mútua o mutex. Això permet a un procés bloquejar una secció de codi per prevenir el seu ús per altres processos. Podries utilitzar semàfors per separat per protegir diferents seccions crítiques d'un programa. Això estalvia crear tots els objectes d'exclusió mútual abans que l'aplicació multi-procés comenci per evitar les condicions d'execució.

El llistat 2-3 és un exemple de codi que utilitza self com el mutex per sincronitzar un mètode d'instància. Aquest tipus de sincronitzacióde fils treballa millor amb "singletons" excepte que vulguis sincronitzar un mètodes cridat a nivell d'instància. Per exemple, si dos fils instancien instàncies separades de la mateixa classe, ambdos poden cridar al mètode de sincronització a l'hora. Pots veure una aproximació semblant per sincronitzar un mètode de clase, on self referencia a la pròpia classe. En aquest cas, només es permet que un fil a la vegada executi el mètode doncs les classes tenen abast global.

Llistat 2-3: Bloquejant un mètode utilitzant self

- (void)metodeCritic
{
    @synchronized(self) {
        // codi crític.
        ...
    }
}

El llistat 2-4 utilitza l'actual selector, _cmd, com el "mutex". Aquest tipus de sincronització només és beneficiosa quan el mètode sincronitzat té un nom únic. Això és així doncs cap altre objecte o classe pot permetre executar un mètode amb el mateix nom fins que el mètode actual finalitzi.

Llistat 2-4: Proquejant un mètode utilitzant _cmd

- (void)metodeCritic
{
    @synchronized(NSStringFromSelector(_cmd)) {
        // Codi crític.
        ...
    }
}

El llistat 2-5 mostra una aproximació general. Abans d'executar el procés crític, el codi obté un semàfor de la classe Account i l'utilitza per bloquejar la secció crítica. La classe Account pot crear el semàfor en el seu mètode initialize.

Llistat 2-5: Bloquejant un mètode utilitzant un semàfor personalitzat

Account *account = [Account accountFromString:[accountField stringValue]];

// Obté el semàfor.
id accountSemaphore = [Account semaphore];

@synchronized(accountSemaphore) {
    // Codi crític.
    ...
}

La característica de sincronització de l'Objective-C suporta la recursivitat i el codi reentrant (no em pregunteu que és). Un procés pot utilitzar un únic semàfor varis cops d'una manera recursiva, però altres processos estaràn bloquejats utilitzant-lo fins que el procés alliberi tots els bloquejos obtinguts amb ell; així cada bloc @synchronized() és finalitzat normalment o llançant una excepció.

Quan el codi d'un bloc @synchronized() llença una excepció, l'excecució de l'Objective-C captura l'excepció, allivera els semafors (per que el codi protegir pugui executar-se per altres processos), i re-llença la excepció al següent capturador d'excepcions.