2012-02-27 15 views
6
static pthread_mutex_t gLock; //global 

pthread_mutex_init(&gLock,NULL); //in init 

pthread_mutex_lock(&gLock); 
for(int i=0;i<[message count];i++) 
CFSetAddValue(mSet, [message objectAtIndex:i]); 
pthread_mutex_unlock(&gLock); 

Mi aplicación de cacao entra en modo no responde con pthread_mutex_t.pthread_mutex_t VS @synchronized block?

@synchronized(mSet) 
{ 
for(int i=0;i<[message count];i++) 
    CFSetAddValue(mSet, [message objectAtIndex:i]); 
} 

Mi aplicación está funcionando bien con el bloque sincronizado.

¿Por qué?

Respuesta

8

Está comparando un bloqueo global (un bloqueo para todas las instancias) con un bloqueo recursivo a nivel de objeto (un bloqueo por instancia, que puede adquirirse varias veces desde el mismo subproceso). En general, estos no son intercambiables; funcionan y se protegen de forma muy diferente.

La buena noticia es que puede usar pthread_mutex_t como un bloqueo recursivo que es exclusivo de cada instancia con el fin de lograr el mismo grado de protección que @synchronized. Usar pthread_mutex_t también hace que las adquisiciones de bloqueos sean mucho, mucho más rápidas.

Para lograr el mismo efecto que @synchronized usando un mutex pthread, declare pthread_mutex_t gLock como una variable de instancia, inícielo como un mutex recursivo en -init. Finalmente, destruya el mutex en -dealloc.

Por supuesto, las clases sub y base pueden necesitar acceso a este bloqueo si se basaron en la semántica de @synchronized para hacer lo correcto a través de la jerarquía de objetos.

@synchronized es veeeeeeery lento en comparación con un mutex pthread recursivo (la última vez que lo comprobé).

+1

En. Archivo \t pthread_mutexattr_t attr; \t pthread_mutex_t mutex; en init \t \t pthread_mutexattr_settype (& attr, PTHREAD_MUTEX_RECURSIVE); \t \t pthread_mutex_init (y exclusión mutua, &attr); en dealloc pthread_mutex_destroy (y mutex); en mi pthread_mutex_lock función (y mutex); \t \t \t \t CFSetRemoveAllValues ​​(MySet); \t \t \t pthread_mutex_unlock (y mutex); es ¿Esta multa? –

+1

@ParagBafna a) el mutex attr puede ser 'estático', y se usa para cada mutex que cree, o no estático y se usa solo en' -init' b) el mutex attr no necesita ser un ivar c) debe verificar su códigos de resultado d) también puede preferir 'pthread_mutex_trylock' en algunos casos. e) debes inicializar las estructuras usando los inicializadores. ¡Aparte de eso, se ve bien! prepárese para el bloqueo rápido =) – justin

+0

los códigos de resultado son útiles principalmente para detectar errores de bloqueo y enhebrado. – justin

0

Justin tiene razón; también hay otro detalle, sin embargo, que es el manejo de excepciones. De https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html viene este consejo:

Como medida de precaución, el bloque @synchronized añade implícitamente un manejador de excepciones al código protegido. Este controlador libera automáticamente el mutex en caso de que se genere una excepción. Esto significa que para usar la directiva @synchronized, también debe habilitar el manejo de excepciones de Objective-C en su código. Si no desea la sobrecarga adicional causada por el manejador de excepciones implícito, debería considerar usar las clases de bloqueo.

Si [message count] puede generar excepciones que podrían saltar sobre su código de desbloqueo y aumentar su nivel.

+0

... si puede recuperarse. la mayoría de las excepciones de cacao no son recuperables (al menos, si desea ejecución predecible a partir de entonces). el caso común para una excepción recuperable sería C++ (recuperación predecible). – justin

Cuestiones relacionadas