Bloque sincronizado: son variables "dentro" de otras variables actualizadas
Lo siento por el título no técnico, pero creo que resume bien mi pregunta. Si interpreto lo que he leído correctamente, el bloqueo sincronizado (aparte de otras consecuencias) hará que todas las variables sean actualizadas a / desde la memoria principal (incluso aquellas a las que no se accede explícitamente dentro del bloque sincronizado, solo su "padre"?) . Por ejemplo, citando la respuesta de esta pregunta stackoverflow (lo tomé fuera de contexto, volveré a él más adelante):
La barrera de memoria se aplica a todas las referencias de memoria, incluso las no relacionadas.
Necesito confirmación si interpreto esto correctamente. Tengo 2 subprocesos (threadA, threadB). Considere el siguiente código:
public class SomeClass { private final Object mLock = new Object(); private int[] anArray; public void initA() { synchronized(mLock) { ... anArray = new int[...]; operationA(); } } public void operationA() { synchronized(mLock) { // Manipulating the ELEMENTS of anArray, // eg in loops, etc. anArray[i] = ... } } public int[] getterB() { synchronized(mLock) { return anArray; } } }
getterB()
se llama desde ThreadB , initA()
y operationA()
se llaman desde ThreadA . (Tenga en cuenta que initA()
se llama incluso antes de ThreadB se crea, por lo que sólo getterB()
y operationA()
son concurrentes.) También tenga en cuenta que tengo una buena razón para no devolver una copia de la matriz en getterB()
, ThreadB no quiere cambiar sus elementos, la razón es un requisito externo para mi software que no es relevante ahora).
ThreadB hace lo siguiente:
int[] anArray = aSomeClass.getterB(); // aSomeClass is an instance of SomeClass if (anArray[i] == n) { ....... } // various operations ... // various other operations that read the elements of anArray
Como se puede ver, en getterB()
, sólo se accede a la referencia anArray
dentro de las barreras de memoria, y no a los valores del array en sí. Mis preguntas:
-
¿ Se verá el threadB los valores del elemento de la matriz más actualizados? (Es decir, son los propios elementos actualizados también de la memoria principal en
getterB()
?) -
La declaración citada mencionó que las copias en caché no relacionadas se actualizan desde la memoria principal también. No soy 100% cómo interpretar esto sin relación (no relacionado con la variable utilizada para bloquear? O no relacionado con el bloque sincronizado entero?). Sé que tomé la cotización fuera de contexto, y puesto que es una pregunta diferente del stackoverflow, he agregado un comentario allí . Así que aprecio si esa pregunta mía es contestada allí (o aquí – no me importa).
-
¿Hay alguna diferencia en la respuesta si
anArray
es una matriz de objetos (y no de tipos primitivos)? Ir aún más lejos, ¿qué pasa si no es una matriz, sino una clase que contiene referencias a otras clases? (Es decir, un objeto que se refiere a otros objetos, y acceder a los objetos contenidos a través del objeto devuelto porgetterB()
). ¿ Utilizará KB las copias actualizadas de estas referencias contenidas , o puede utilizar sus propias copias locales en caché (puesto quegetterB()
sólo actualizó su objeto de contenedor, pero no las propias referencias contenidas) ?.
- Mostrar imágenesVistas con tema de animación
- Traducción de código Python a JVM
- ¿Cómo puedo acceder a una conexión SSL a través de Android?
- Cómo hacer http obtener solicitud en Android
- Causado por: java.lang.IllegalStateException: ¿paquete no instalado?
- Eliminar SMS en Android 1.5
- Flickr Oauth Conectarse con Scribe Library
- Cómo configurar el gestor de Android SDK con calcetines?
Tomando sus preguntas en orden:
-
Sí: Se puede asumir con seguridad que todos los valores modificados desde cualquier
operationA()
previamente llamadaoperationA()
serán "up-to-date" en la matriz referenciada por el resultado degetterB()
. -
Dejaré que se responda en el otro enlace; Confieso que todavía no leí ese enlace. Pero mi comprensión es que todos los write-backs pendientes de la memoria ocurrirán "con eficacia" mientras que ambos entran y salen de un bloque sincronizado (aunque los detalles de cómo éste sucede – es decir, la eficacia de esto, y si hay más cache / pipelining "Trucos" pasando a hacer que aparezca de esa manera – dependerá del hardware y compilador). Si desea más detalles sobre esto, una vez encontré este enlace útil: http://www.infoq.com/articles/memory_barriers_jvm_concurrency
-
No, no hay diferencia (dado lo que escribí en la respuesta 2).
Por último, sólo un comentario que sería muy cauteloso de su código como se resume más arriba debido al hecho de que getterB()
no devuelve una copia de la matriz. Entiendo que usted tiene sus razones para hacerlo de la manera anterior (y que no quería este tipo de comentarios!), Pero usted debe estar seguro de entender que todas las "diversas operaciones" en el hilo B
en anArray
que Ocurren después de que getterB()
haya devuelto no estará protegido. (En otras palabras, habrá riesgos con cualquier cambio en el arreglo realizado en el hilo A
durante este tiempo). Una alternativa que evitaría una copia ineficaz de array profundo es mover estas "diversas operaciones" dentro de un bloque sincronizado dentro de un nuevo método En SomeClass
y deshacerse completamente de getterB()
. Por supuesto, me doy cuenta de que la "solución correcta" en su código depende de muchas cosas que no se muestran aquí, así que no dude en ignorar este bit.
- Android – ¿es posible saber qué aplicación tiene audiofocus?
- Cómo implementar el anuncio de mediación en android