Tengo algunas preguntas sobre el uso y la importancia de la synchronized
palabra clave.
- ¿Cuál es el significado de la
synchronized
palabra clave? - ¿Cuándo deberían ser los métodos
synchronized
? - ¿Qué significa programática y lógicamente?
java
multithreading
keyword
synchronized
Johanna
fuente
fuente
Respuestas:
La
synchronized
palabra clave trata sobre diferentes hilos que leen y escriben en las mismas variables, objetos y recursos. Este no es un tema trivial en Java, pero aquí hay una cita de Sun:En pocas palabras: cuando tienes dos hilos que leen y escriben en el mismo 'recurso', digamos una variable llamada
foo
, debes asegurarte de que estos hilos accedan a la variable de forma atómica. Sin lasynchronized
palabra clave, es posible que su hilo 1 no vea el cambio hecho en el hilo 2foo
o, lo que es peor, solo se puede cambiar a medias. Esto no sería lo que lógicamente espera.Nuevamente, este es un tema no trivial en Java. Para obtener más información, explore los temas aquí sobre SO y las Interwebs sobre:
Siga explorando estos temas hasta que el nombre "Brian Goetz" se asocie permanentemente con el término "concurrencia" en su cerebro.
fuente
Bueno, creo que ya tuvimos suficientes explicaciones teóricas, así que considera este código
Nota:
synchronized
bloquea la llamada del siguiente subproceso al método test () siempre que la ejecución del subproceso anterior no haya finalizado. Los hilos pueden acceder a este método uno a la vez. Sinsynchronized
todos los hilos pueden acceder a este método simultáneamente.Cuando un hilo llama al método sincronizado 'prueba' del objeto (aquí el objeto es una instancia de la clase 'TheDemo') adquiere el bloqueo de ese objeto, cualquier hilo nuevo no puede llamar a NINGÚN método sincronizado del mismo objeto siempre que el hilo anterior que había adquirido el bloqueo no libera el bloqueo.
Algo similar ocurre cuando se llama a cualquier método estático sincronizado de la clase. El subproceso adquiere el bloqueo asociado con la clase (en este caso, cualquier subproceso sincronizado no estático de una instancia de esa clase puede ser llamado por cualquier subproceso porque ese bloqueo de nivel de objeto todavía está disponible). Cualquier otro subproceso no podrá llamar a ningún método estático sincronizado de la clase, siempre que el subproceso de nivel de clase no se libere por el subproceso que actualmente mantiene el bloqueo.
Salida con sincronizado
Salida sin sincronizado
fuente
synchronized
, pero se ignora la coherencia de la memoria.La
synchronized
palabra clave evita el acceso concurrente a un bloque de código u objeto por múltiples hilos. Todos los métodos deHashtable
sonsynchronized
, por lo que solo un subproceso puede ejecutar cualquiera de ellos a la vez.Cuando utilice no
synchronized
construcciones comoHashMap
, debe crear características de seguridad de subprocesos en su código para evitar errores de coherencia.fuente
synchronized
significa que en un entorno de subprocesos múltiples, un objeto que tienesynchronized
método (s) / bloque (s) no permite que dos subprocesos accedan alsynchronized
método (s) / bloque (es) de código al mismo tiempo. Esto significa que un hilo no puede leer mientras otro hilo lo actualiza.El segundo hilo esperará hasta que el primer hilo complete su ejecución. La sobrecarga es la velocidad, pero la ventaja es la consistencia garantizada de los datos.
Sin embargo, si su aplicación es de un solo subproceso, los
synchronized
bloques no proporcionan beneficios.fuente
La
synchronized
palabra clave hace que un subproceso obtenga un bloqueo al ingresar el método, por lo que solo un subproceso puede ejecutar el método al mismo tiempo (para la instancia de objeto dada, a menos que sea un método estático).Esto se llama con frecuencia hacer que la clase sea segura para subprocesos, pero yo diría que esto es un eufemismo. Si bien es cierto que la sincronización protege el estado interno del Vector para que no se corrompa, esto generalmente no ayuda mucho al usuario de Vector.
Considera esto:
A pesar de que los métodos involucrados están sincronizados, debido a que se están bloqueando y desbloqueando individualmente, dos hilos desafortunadamente pueden crear un vector con dos elementos.
En efecto, también debe sincronizar el código de su aplicación.
Debido a que la sincronización a nivel de método es a) costosa cuando no la necesita yb) insuficiente cuando necesita sincronización, ahora hay reemplazos no sincronizados (ArrayList en el caso de Vector).
Más recientemente, se lanzó el paquete de simultaneidad, con una serie de utilidades inteligentes que se ocupan de problemas de subprocesos múltiples.
fuente
Visión general
La palabra clave sincronizada en Java tiene que ver con la seguridad de subprocesos, es decir, cuando varios subprocesos leen o escriben la misma variable.
Esto puede suceder directamente (accediendo a la misma variable) o indirectamente (usando una clase que usa otra clase que accede a la misma variable).
La palabra clave sincronizada se usa para definir un bloque de código donde múltiples hilos pueden acceder a la misma variable de manera segura.
Más adentro
En cuanto a la sintaxis, la
synchronized
palabra clave toma unObject
parámetro como es (llamado un objeto de bloqueo ), que luego es seguido por un{ block of code }
.Cuando la ejecución encuentra esta palabra clave, el hilo actual intenta "bloquear / adquirir / poseer" (elija) el objeto de bloqueo y ejecutar el bloque de código asociado después de que se haya adquirido el bloqueo.
Se garantiza que cualquier escritura en variables dentro del bloque de código sincronizado será visible para cualquier otro subproceso que ejecute de manera similar el código dentro de un bloque de código sincronizado utilizando el mismo objeto de bloqueo .
Solo un subproceso a la vez puede retener el bloqueo, durante el cual todos los demás subprocesos que intentan adquirir el mismo objeto de bloqueo esperarán (pausarán su ejecución). El bloqueo se liberará cuando la ejecución salga del bloque de código sincronizado.
Métodos sincronizados:
Adición de
synchronized
palabra clave para una definición de método es igual a todo el cuerpo del método de ser envuelto en un bloque de código sincronizado con el objeto de bloqueo serthis
(para los métodos de instancia) yClassInQuestion.getClass()
(para los métodos de clase) .- El método de instancia es un método que no tiene
static
palabra clave.- El método de clase es un método que tiene
static
palabra clave.Técnico
Sin sincronización, no se garantiza en qué orden ocurren las lecturas y escrituras, posiblemente dejando la variable con basura.
(Por ejemplo, una variable podría terminar con la mitad de los bits escritos por un hilo y la mitad de los bits escritos por otro hilo, dejando la variable en un estado que ninguno de los hilos intentó escribir, sino un desorden combinado de ambos).
No es suficiente completar una operación de escritura en un hilo antes (tiempo de reloj de pared) de que otro hilo lo lea, porque el hardware podría haber almacenado en caché el valor de la variable, y el hilo de lectura vería el valor almacenado en caché en lugar de lo que se escribió eso.
Conclusión
Por lo tanto, en el caso de Java, debe seguir el Modelo de memoria de Java para asegurarse de que no se produzcan errores de subprocesamiento.
En otras palabras: use sincronización, operaciones atómicas o clases que los usen para usted bajo los capó.
fuente
Piense en ello como una especie de torniquete como el que podría encontrar en un campo de fútbol. Hay vapores paralelos de personas que desean entrar pero en el torniquete están 'sincronizados'. Solo una persona a la vez puede pasar. Todos aquellos que quieran pasar lo harán, pero pueden tener que esperar hasta que puedan pasar.
fuente
Los hilos se comunican principalmente compartiendo el acceso a los campos y los campos de referencia de los objetos a los que se refieren. Esta forma de comunicación es extremadamente eficiente, pero hace posibles dos tipos de errores: interferencia de hilo y errores de consistencia de memoria . La herramienta necesaria para evitar estos errores es la sincronización.
Los bloques o métodos sincronizados evitan la interferencia del hilo y aseguran que los datos sean consistentes. En cualquier momento, solo un subproceso puede acceder a un bloque o método sincronizado ( sección crítica ) mediante la adquisición de un bloqueo. Otros hilos esperarán a que se libere el bloqueo para acceder a la sección crítica .
Los métodos se sincronizan cuando agrega
synchronized
a la definición o declaración del método. También puede sincronizar un bloque de código particular con un método.Significa que solo un hilo puede acceder a la sección crítica mediante la adquisición de un bloqueo. A menos que este hilo libere este bloqueo, todos los otros hilos tendrán que esperar para adquirir un bloqueo. No tienen acceso para ingresar a la sección crítica sin adquirir el bloqueo.
Esto no se puede hacer con una magia. Es responsabilidad del programador identificar las secciones críticas en la aplicación y protegerlas en consecuencia. Java proporciona un marco para proteger su aplicación, pero dónde y qué deben protegerse todas las secciones es responsabilidad del programador.
Más detalles en la página de documentación de Java
Cerraduras intrínsecas y sincronización:
Cada objeto tiene un bloqueo intrínseco asociado . Por convención, un hilo que necesita acceso exclusivo y consistente a los campos de un objeto tiene que adquirir el bloqueo intrínseco del objeto antes de acceder a ellos, y luego liberar el bloqueo intrínseco cuando se hace con ellos.
Se dice que un subproceso posee el bloqueo intrínseco entre el momento en que adquirió el bloqueo y lo liberó. Mientras un hilo posea un bloqueo intrínseco, ningún otro hilo puede adquirir el mismo bloqueo. El otro hilo se bloqueará cuando intente adquirir el bloqueo.
Hacer métodos sincronizados tiene dos efectos :
Cuando un subproceso está ejecutando un método sincronizado para un objeto, todos los demás subprocesos que invocan métodos sincronizados para el mismo bloque de objeto (suspender la ejecución) hasta que el primer subproceso se realiza con el objeto.
Esto garantiza que los cambios en el estado del objeto sean visibles para todos los hilos.
Busque otras alternativas a la sincronización en:
¿Evitar sincronizado (esto) en Java?
fuente
Synchronized normal method
equivalente aSynchronized statement
(use esto)Synchronized static method
equivalente aSynchronized statement
(usar clase)Sentencia sincronizada (usando variable)
Para
synchronized
, tenemos ambosSynchronized Methods
ySynchronized Statements
. Sin embargo,Synchronized Methods
es similar aSynchronized Statements
lo que necesitamos entenderSynchronized Statements
.=> Básicamente, tendremos
Aquí hay 2 pensamientos que ayudan a entender
synchronized
intrinsic lock
asociado con él.synchronized statement
, automáticamente adquiere elintrinsic lock
para esesynchronized statement's
objeto y lo libera cuando el método regresa. Mientras un hilo posea unintrinsic lock
, NINGÚN otro hilo puede adquirir el MISMO bloqueo => hilo seguro.=> Cuando se
thread A
invocasynchronized(this){// code 1}
=> todo el código de bloqueo (dentro de la clase) donde havesynchronized(this)
y allsynchronized normal method
(dentro de la clase) está bloqueado porque el MISMO bloqueo. Se ejecutará después delthread A
desbloqueo ("// código 1" terminado).Este comportamiento es similar a
synchronized(a variable){// code 1}
osynchronized(class)
.MISMO BLOQUEO => bloqueo (¿no depende de qué método o qué afirmaciones?)
¿Usar método sincronizado o declaraciones sincronizadas?
Prefiero
synchronized statements
porque es más extensible. Ejemplo, en el futuro, solo necesita sincronizar una parte del método. Por ejemplo, tiene 2 métodos sincronizados y no tiene ninguna relevancia entre sí, sin embargo, cuando un subproceso ejecuta un método, bloqueará el otro método (puede evitarlo mediante el usosynchronized(a variable)
).Sin embargo, aplicar el método sincronizado es simple y el código parece simple. Para alguna clase, solo hay 1 método sincronizado, o todos los métodos sincronizados en la clase son relevantes entre sí => podemos usar
synchronized method
para hacer el código más corto y fácil de entenderNota
(no es relevante para mucho
synchronized
, es la diferencia entre objeto y clase o no estático y estático).synchronized
un método normalsynchronized(this)
osynchronized(non-static variable)
se sincronizará la base en cada instancia de objeto.synchronized
método estáticosynchronized(class)
osynchronized(static variable)
se sincronizará en base a la claseReferencia
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Espero que ayude
fuente
Aquí hay una explicación de The Java Tutorials .
Considere el siguiente código:
fuente
A mi entender, sincronizado básicamente significa que el compilador escribe un monitor.enter y monitor.exit alrededor de su método. Como tal, puede ser seguro para subprocesos dependiendo de cómo se use (lo que quiero decir es que puede escribir un objeto con métodos sincronizados que no sean seguros para subprocesos dependiendo de lo que haga su clase).
fuente
Lo que faltan las otras respuestas es un aspecto importante: las barreras de memoria . La sincronización de subprocesos consiste básicamente en dos partes: serialización y visibilidad. Aconsejo a todos que busquen en Google "barrera de memoria jvm", ya que es un tema no trivial y extremadamente importante (si modifica los datos compartidos a los que acceden varios subprocesos). Una vez hecho esto, le aconsejo que mire las clases del paquete java.util.concurrent que ayudan a evitar el uso de la sincronización explícita, lo que a su vez ayuda a mantener los programas simples y eficientes, tal vez incluso evitando puntos muertos.
Un ejemplo de ello es ConcurrentLinkedDeque . Junto con el patrón de comando , permite crear subprocesos de trabajo altamente eficientes al rellenar los comandos en la cola concurrente: no se necesita sincronización explícita, no hay puntos muertos posibles, no es necesario dormir (), solo sondea la cola llamando a take ().
En resumen: la "sincronización de memoria" ocurre implícitamente cuando inicia un subproceso, un subproceso finaliza, lee una variable volátil, desbloquea un monitor (deja un bloque / función sincronizado), etc. Esta "sincronización" afecta (en cierto sentido, "se sonroja"). ") todas las escrituras hechas antes de esa acción en particular. En el caso del mencionado ConcurrentLinkedDeque , la documentación "dice":
Este comportamiento implícito es un aspecto un tanto pernicioso porque la mayoría de los programadores de Java sin mucha experiencia solo tomarán mucho por lo debido. Y de repente tropezar con este hilo después de que Java no está haciendo lo que se supone que debe hacer en la producción donde hay una carga de trabajo diferente, y es bastante difícil probar los problemas de concurrencia.
fuente
Sincronizado simplemente significa que múltiples hilos si están asociados con un solo objeto pueden evitar la lectura y escritura sucias si se usa un bloque sincronizado en un objeto en particular. Para darle más claridad, tomemos un ejemplo:
Hemos creado dos objetos de clase MyRunnable, runnable1 se comparte con el hilo 1 y el hilo 3 y runnable2 se comparte solo con el hilo 2. Ahora, cuando t1 y t3 se inician sin que se use sincronizado, la salida PFB sugiere que ambos subprocesos 1 y 3 afectan simultáneamente el valor de var, donde para el subproceso 2, var tiene su propia memoria.
Usando Synchronzied, thread 3 esperando que se complete el thread 1 en todos los escenarios. Hay dos bloqueos adquiridos, uno en runnable1 compartido por el hilo 1 y el hilo 3 y otro en runnable2 compartido solo por el hilo 2.
fuente
Sincronizado simple significa que no hay dos hilos que puedan acceder al bloque / método simultáneamente. Cuando decimos que cualquier bloque / método de una clase está sincronizado, significa que solo un hilo puede acceder a ellos a la vez. Internamente, el subproceso que intenta acceder primero se bloquea en ese objeto y mientras este bloqueo no esté disponible, ningún otro subproceso puede acceder a ninguno de los métodos / bloques sincronizados de esa instancia de la clase.
Tenga en cuenta que otro hilo puede acceder a un método del mismo objeto que no está definido para sincronizarse. Un hilo puede liberar el bloqueo llamando
fuente
synchronized
El bloque en Java es un monitor en subprocesamiento múltiple.synchronized
El bloque con el mismo objeto / clase se puede ejecutar con un solo hilo, todos los demás están esperando. Puede ayudar con larace condition
situación cuando varios hilos intentan actualizar la misma variable (el primer paso es usarvolatile
Acerca de )Java 5
extendidosynchronized
apoyandohappens-before
[Acerca de]El siguiente paso es
java.util.concurrent
volátil vs sincronizado
fuente
sincronizado es una palabra clave en Java que se usa para que ocurra antes de la relación en un entorno de subprocesos múltiples para evitar inconsistencias de memoria y errores de interferencia de subprocesos.
fuente