2008-12-08 12 views
5

Yo usuario sun jdk 1.5 ThreadPoolExecutor (24, 24,60, TimeUnit.SECONDS, LinkedBlockingQueue()). soemtime herramienta jdb que utilizo para encontrar el estado de todas las discusiones en grupo de subprocesos están "esperando en un monitor", el código es:interbloqueo en sincronizado (Interno de cadena())

String key = getKey(dt.getPrefix(), id); 
    synchronized (key.intern()) {  -----> 

¿Hay un problema en "sincronizado (key.intern())"?


consigo siguiente informatnio usando la herramienta jdb, el estado de 24 hilos está "esperando en un monitor", significa 24 hilos son de interbloqueo en "key.intern()".

(java.lang.Thread) 0x28 piscina-3-thread-2 esperando en un monitor

(java.lang.Thread) 0x27 piscina-3-thread-3 esperando en un monitor

(java.lang.Thread) 0x1b piscina-3-thread-4 esperando en un monitor

(java.lang.Thread) 0x1a piscina-3-thread-5 esperando en un monitor

(java.lang .Thread) 0x19 pool-3-thread-6 esperando en un monitor

(java.lang.Thread) 0x18 piscina-3-thread-7 espera en un monitor

(java.lang.Thread) 0x17 piscina-3-thread-8 de espera en un monitor ...

por lo que el resultado es: en el entorno de múltiples hilos, el método Sting Intern() puede ser un interbloqueo, ¿de acuerdo?

+0

Primera pregunta es ¿qué quieres lograr? ¿Cuál es el problema? ¿Por qué necesitas sincronizar? –

+0

¿ha mirado los hilos FUERA del subproceso para ver si también están esperando en un monitor? Deberías prestar atención al objeto exacto en el que cada hilo está sincronizado también. –

+0

Hay dos subprocesos fuera del grupo de subprocesos que están esperando en un monitor, y también supervisan la misma línea (key.intern()). – user44230

Respuesta

4

Todo. El problema es que key.intern() no es tan único porque devuelve una cadena de un grupo. String.intern() puede devolver el mismo objeto incluso cuando se usa en objetos diferentes. Intente usar key o un objeto diferente por completo.

-1

String.intern() es un método nativo, que podría ser la causa del problema.

+0

¿Por qué causaría el problema? Creo que el hecho de que el método sea nativo o no tiene ningún impacto, ocurre antes de que comience la sincronización. –

1

Como dice Bombe, key.intern() no necesariamente te dará una clave única para sincronizar.

Sin embargo, debe tener cuidado al cambiar el código. Debe comprender la estrategia de bloqueo en el código antes de cambiarlo. Eliminar la llamada interna() puede darle un código que parece funcionar correctamente pero contiene una carrera de datos que lo morderá más tarde.

2

Es casi seguro que el código intenta sincronizar acciones que afectan a la misma clave. Por lo tanto, está llamando a intern() para garantizar que la misma clave se asigna al mismo objeto y, por lo tanto, es válida como objeto para la sincronización.

El problema, si te encuentras con un cuello de botella allí (no es un punto muerto) es que tienes demasiadas operaciones entrando al mismo tiempo con la misma tecla.

Vuelva a pensar lo que debe sincronizarse.

+0

¿Cómo supiste que estaba hablando de cuello de botella? –

+0

¿Cómo sabes que no es un punto muerto? Usar algo universalmente accesible como una cadena interna es una forma fácil de conseguir un punto muerto. – erickson

+0

la definición de punto muerto es que dos (o más) subprocesos están esperando recursos pertenecientes a los otros. Esto implica dos bloques sincronizados (o un bucle). El código que se muestra, aunque podría estar en un bucle, parece ser una puerta bastante sencilla de sección crítica. – kdgregory

2

Si necesita sincronizar en una Cadena, no use una instancia de Cadena como mutex (interna o no). Sin embargo, una cadena se puede usar para crear un buen objeto mutex: synchronizing on an ID.

2

Usted está teniendo dos problemas. El que está usando String como cerradura. El segundo es un punto muerto.

Si usa String como bloqueo, perderá el control de "quién" y "dónde" tomará ese bloqueo de objeto.

Su problema de interbloqueo, que puede o no causado por el bloqueo en Cadena. Sin embargo, la razón real del punto muerto es: "Tu código puede provocar un interbloqueo". Si puede suceder, sucederá.

Debe rastrear las pilas de sus hilos para resolver los interbloqueos.

+0

¿Qué hay de malo en utilizar String.intern() como bloqueo? Lo he usado con éxito –

+1

Por supuesto, es posible usar un String como cerradura. Sin embargo, por exactamente los motivos mencionados en la respuesta, rara vez es "bueno" (lo que sea que eso signifique) hacerlo. – Bombe

+0

No estoy seguro de entender lo que es malo al respecto. Eso es causa de estancamiento? ¿O que es un cuello de botella? No creo que ninguno sea verdad. –

5

He publicado una pregunta relacionada con esto una vez que es posible que desee echar un vistazo a: Problem with synchronizing on String objects?

Lo que aprendí fue: el uso de cadenas para la sincronización intern'ed es una mala práctica.

+1

Sería útil si detalla por qué es una mala práctica. –

+0

no responde la pregunta vinculada? * al ejecutar pruebas de JMeter contra la aplicación web para simular la carga esperada, vi que el tamaño de almacenamiento dinámico utilizado crecía a casi 1GB en menos de 20 minutos. * –

+3

Sería una mejor respuesta si explicas rápidamente por qué en la respuesta en lugar de dejar que las personas lee una pregunta larga. –

2

No hay suficiente código aquí para decir qué está pasando mal. Podría ser un cuello de botella como se ha mencionado, pero al menos un hilo debería estar ejecutándose (con un uso de CPU bastante pesado) para que eso suceda, o un hilo que tenga el bloqueo se ponga en modo de suspensión sin soltar el bloqueo.

Un punto muerto es otra posibilidad, pero eso requeriría la sincronización en dos bloqueos separados en múltiples hilos, y usted ha mostrado solo un objeto de bloqueo aquí.

Es realmente imposible de determinar sin más información.

1

Es muy probable que tenga un interbloqueo.

Si desea evitar interbloqueos, cada subproceso siempre debe adquirir bloqueos en el mismo orden. Cuando utiliza String.intern() para obtener sus bloqueos, está bloqueando una instancia a la que tiene acceso cualquier código de toda la JVM y la bloquea. Lo más probable es que otros subprocesos en su propio código estén bloqueados, pero no tiene que ser así.

No estoy seguro de lo que quiere decir con "key.intern() guarantee uniqueness" en su respuesta. El método intern()reduce la unicidad de al devolver el mismo objeto por cada cadena que sea equivalente.

String s1 = new String(new char[] { 'c', 'o', 'm', 'm', 'o', 'n' }).intern(); 
    String s2 = new String("commo" + (s1.charAt(s1.length() - 1)).intern(); 
    String s3 = "common"; 
    if ((s1 == s2) && (s1 == s3)) 
    System.out.println("There's only one object here."); 

El código anterior demostrar que a pesar de que ha creado dos instancias únicas, a través de pasantías ellos, se les reemplaza con una sola instancia, canónica.

Existe un peligro cada vez que utiliza un objeto que está visible fuera de su propio código como un candado. Trate de apegarse a miembros privados, objetos que no permite escapar de su propia pila, etc.

0

¿Qué le parece usar un único prefijo de cadena con el valor de bloqueo y el uso de String?interno() en el bloque sincronizado. Por ejemplo, si desea bloquear la cadena "lock1", use un prefijo UUID como este: "85e565b3-d440-46e7-93b6-69ee7e9a63ee-lock1". Este tipo de cadena no debería estar ya en el grupo interno. es decir, la probabilidad de estancamiento por otro código es muy baja.

Cuestiones relacionadas