2012-09-06 14 views
12

dado:Haciendo un Hilo de seguridad de clase

public class TestSeven extends Thread { 

private static int x; 

public synchronized void doThings() { 
    int current = x; 
    current++; 
    x = current; 
} 

public void run() { 
    doThings(); 
    } 
} 

¿Qué afirmación es verdadera?

A. La compilación falla.

B. Se produce una excepción en el tiempo de ejecución.

C. Sincronizar el método run() haría la clase segura para subprocesos.

D. Los datos en la variable "x" están protegidos contra problemas de acceso concurrente.

E. Declarar el método doThings() como estático haría que la clase fuera de subprocesos.

F. Envolver las instrucciones dentro de doThings() en un bloque sincronizado (nuevo Object()) {} haría que la clase sea segura para subprocesos.

¿no es suficiente marcar doThings() como sincronizado para hacer que la clase sea segura para subprocesos? Veo que la respuesta correcta es D pero la respuesta modelo de esta pregunta es E, pero no entiendo por qué?

Respuesta

17

E. Declarar el método doThings() como estático haría que la clase sea segura para subprocesos.

Esa es una respuesta un poco complicada. El método ya está sincronizado, pero en la instancia, mientras que el estado está en un campo estático, es decir, en la clase. Hacerlo static synchronized es de hecho la respuesta correcta, porque luego se sincroniza en la clase, no en una instancia (sin sentido).

D. Los datos en la variable "x" están protegidos contra problemas de acceso concurrente.

private static int x; 

Ésta es una variable estática. Es compartido por todas las instancias de la clase, por lo que la sincronización en instancias individuales no es útil, del mismo modo que F no sería útil, que se sincroniza en un objeto ficticio completo desechable.

11

Según la language spec:

Un método sincronizado adquiere un monitor (§17.1) antes de que se ejecuta.

Para un método de clase (estático), se utiliza el monitor asociado con el objeto Clase para la clase del método.

Para un método de instancia, se utiliza el monitor asociado a esto (el objeto para el que se invocó el método).

Esto significa que en el código que ya ha proporcionado la palabra clave synchronized hace que el método para adquirir un bloqueo en this antes de ejecutar el cuerpo del método. Sin embargo, dado que x es static, eso no garantiza que la actualización a x sea atómica. (Otra instancia de la clase podría ingresar a la región sincronizada y hacer una actualización al mismo tiempo, ya que tienen diferentes valores this y, por lo tanto, diferentes bloqueos.)

Sin embargo, declarar doStuff estático hará que todas las llamadas al método adquieran el mismo bloqueo (el del Class) y así garantizaría la exclusión mutua en el cuerpo del método.

Las especificaciones se realmente que explican que:

class A { 
    static synchronized void doSomething() { 
     // ... 
    } 
} 

es, literalmente, lo mismo que

class A { 
    static void doSomething() { 
     synchronized(A.class) { 
      // ... 
     } 
    } 
} 

mismo modo:

class B { 
    synchronized void doSomething() { 
     // ... 
    } 
} 

es literalmente el mismo que

class B { 
    void doSomething() { 
     synchronized (this) { 
      // ... 
     } 
    } 
} 
6

Al sincronizar el método doThings(), está manteniendo el bloqueo para un objeto TestSeven en particular. Sin embargo, las variables estáticas de la clase no pertenecen a la instancia específica del objeto en sí. Pertenecen al objeto Class TestSeven.class. Así que, o usted podría ir para un

synchronized (TestSeven.class){ 
    int current = x; 
    current++; 
    x = current; 
} 
() método

dentro de sus doThings que está adquiriendo la cerradura de clase dentro de un registro de estancia que está exagerando las cosas. Por lo tanto, puede marcar el método como estático para que termine adquiriendo el bloqueo del objeto Class solo.

-6

Estoy de acuerdo con usted en que la respuesta correcta es D. diría que E es incorrecta porque si fijo (doThings) como estática y quitar la palabra clave sincronizada, tan sólo pudiera poner en marcha 50 TestSeven hilos y que podría resultar en valor x incorrecto

Nota: Me equivoqué aquí, me olvidé de señalar que el método sincronizado sin estática realmente usa la instancia como el monitor de bloqueo en lugar de la clase misma.

+3

D no es correcto. – Keppil

+1

E es correcto porque no dice "eliminar la palabra clave sincronizada". Frase innecesariamente difícil, pero eso es lo que obtienes en estos exámenes. – Thilo

+0

D es correcto, ya que con la clase dada no hay otra forma de cambiar el valor de x. Si se permite agregar otro método, entonces diría que incluso la solución E no es correcta. –

1

Dado que x es static otros hilos podrían modificarlo al mismo tiempo doThings método se está ejecutando. Hacer doThingsstatic detendrá esto.

Cuestiones relacionadas