2009-08-01 5 views
6

¿Puedo hacer algo de lo siguiente? ¿Bloquearán/desbloquearán correctamente el mismo objeto? ¿Por qué o por qué no? Supongamos que hay muchos subprocesos idénticos que usan la variable global "obj", que se inicializó antes de que se iniciaran todos los subprocesos.Cambiar el objeto de bloqueo dentro de la sección @ sincronizada

1.

@synchronized(obj) { 
    [obj release]; 
    obj = nil; 
} 

2.

@synchronized(obj) { 
    obj = [[NSObject new] autorelease]; 
} 
+0

Nota: relacionado con http://stackoverflow.com/questions/1215330/ –

+1

Después de leer esta publicación SO, decidí investigar @synchronized un poco más a fondo y escribir una publicación en el blog. Puede encontrarlo útil: http://rykap.com/objective-c/2015/05/09/synchronized.html – rjkaplan

+0

@rjkaplan su enlace está roto –

Respuesta

8

Respuesta corta: no, no quedará fija/desbloqueo, y tales métodos deben ser evitados.

Mi primera pregunta es por qué querrías hacer algo como esto, ya que estos enfoques anulan los propósitos y beneficios de usar un bloque @synchronized en primer lugar.

En su segundo ejemplo, una vez que un hilo cambia el valor de obj, cada hilo subsiguiente que llegue al bloque @synchronized se sincronizará en el nuevo objeto, no en el objeto original. Para N subprocesos, estaría creando explícitamente N objetos liberados automáticamente, y el tiempo de ejecución puede crear hasta N bloqueos recursivos asociados con esos objetos. Intercambiar el objeto en el que se sincroniza dentro de la sección crítica es un no-no fundamental de la concurrencia de subprocesos seguros. No lo hagas Nunca. Si varios hilos pueden acceder de forma segura a un bloque al mismo tiempo, simplemente omita por completo el @synchronized.

En su primer ejemplo, los resultados pueden estar indefinidos, y ciertamente tampoco son lo que usted desea. Si el tiempo de ejecución solo utiliza el puntero del objeto para encontrar el bloqueo asociado, el código puede funcionar bien, pero la sincronización en nil no tiene efecto perceptible en mis pruebas simples, así que de nuevo estás usando @synchronized de una manera inútil, ya que no ofrece protección alguna.

Honestamente, no trato de ser duro, ya que supongo que probablemente solo tengas curiosidad sobre la construcción. Solo estoy redactando esto con fuerza para (con suerte) evitar que usted y otros escriban código que tiene fallas fatales, especialmente si se supone que se sincroniza correctamente. ¡Buena suerte!

+0

En mi caso particular (la razón por la que encontré esto Q/A) es que quiero hacer algo como (lo siento, no hay un buen formato en los comentarios) ... '@synchornized (obj) {if (obj! = Nil) {... [hacer cosas, recortar]; obj = nil}} '(* NOTA: * Estoy bajo ARC, así que obtengo mi 'release' gratis. Lo que quiero es, si hay un obj, sincronizarlo mientras yo ando por ahí. Si es nulo, realmente no me importa – Olie

Cuestiones relacionadas