Por qué la sincronización de hilos
Porque cuando tenemos múltiples hilos para acceder a una variable u objeto al mismo tiempo, si hay operaciones de lectura y escritura en estos hilos, causará confusión en el valor de la variable u estado del objeto, lo que resulta en excepciones del programa. Por ejemplo, si una cuenta bancaria es operada por dos hilos al mismo tiempo, uno retira 100 yuanes y el otro ahorra 100 yuanes. Suponiendo que la cuenta originalmente tenía 0 yuan, ¿qué pasaría si el hilo de retiro y el hilo de salvación ocurrieran al mismo tiempo? Si el retiro del dinero no es exitoso, el saldo de la cuenta es 100. Si el retiro del dinero es exitoso, el saldo de la cuenta es 0. Entonces, ¿cuál es? Es difícil de explicar claramente. Por lo tanto, la sincronización multiproceso es resolver este problema.
1. Código cuando está fuera de sincronización
Bank.Java Package ThreadTest; out .println (System.CurrentTimemillis ()+"Save:"+Money); :::::::::::::::::: para::: ::::::::::::::::::::::::::::::: :::::::::::::::::: para::: ::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::: no "Take Out:"+Money); (String args []) {Final Bank Bank = new B Ank (); Tad = New Thread (new Runnable () { @ anverride public void run () {// TODO Auto Generado Stub while (true) {Thread.sleep (1000); /n ");}}}); Thread tsub = new Thread (new runnable () {@Override public void run () {// TODO Auto Generado Stub While (True) {Bank.SubMoney (100); Bank; Bank; .SightMoney (); });
El código es muy simple, no lo explicaré. Intercepté algunos de ellos, ¿es muy desordenado y no puedo entender la escritura?
Saldo insuficiente Saldo de la cuenta: 0
Saldo insuficiente Saldo de la cuenta: 100
1441790503354 Depósito: 100
Saldo de la cuenta: 100
1441790504354 Depósito: 100
Saldo de la cuenta: 100
1441790504354 Take Out: 100
Saldo de la cuenta: 100
1441790505355 Depósito: 100
Saldo de la cuenta: 100
1441790505355 Take Out: 100
Saldo de la cuenta: 100
2. Use el código sincrónico
(1) Método de sincronización:
Hay un método para modificar las palabras clave sincronizadas. Dado que cada objeto en Java tiene un bloqueo incorporado, al modificar el método con esta palabra clave, el bloqueo incorporado protege todo el método. Antes de llamar a este método, debe obtener un bloqueo incorporado, de lo contrario estará en un estado de bloqueo.
Banco modificado.java
Echemos un vistazo a los resultados de la ejecución:
Saldo insuficiente Saldo de la cuenta: 0
Saldo insuficiente Saldo de la cuenta: 0
14417908373380 Saved: 100
Saldo de la cuenta: 100
1441790838380 Take Out: 100
Saldo de la cuenta: 0
1441790838380 Saved: 100
Saldo de la cuenta: 100
1441790839381 eliminado: 100
Saldo de la cuenta: 0
Siento que entiende al instante.
Nota: La palabra clave sincronizada también puede modificar métodos estáticos.
(2) Sincronizar bloques de código
Es decir, hay un bloque de instrucción modificado por palabra clave sincronizada. El bloque de instrucciones modificado por esta palabra clave se agregará automáticamente con un bloqueo incorporado para lograr la sincronización
El código de Bank.Java es el siguiente:
paquete threadtest; System.out.println (System.CurrentTimemillis ()+"Save:"+Money); .println ("Balance insuficiente"); {System.out.println ("Saldo de la cuenta:"+Count);
Los resultados de la operación son los siguientes:
Saldo insuficiente Saldo de la cuenta: 0
1441791806699 Saved: 100
Saldo de la cuenta: 100
1441791806700 Take Out: 100
Saldo de la cuenta: 0
1441791807699 Saved: 100
Saldo de la cuenta: 100
El efecto es similar al método.
Nota: La sincronización es una operación de alto nivel, por lo que se debe minimizar el contenido sincronizado. Por lo general, no hay necesidad de sincronizar todo el método, solo use el bloque de código sincronizado para sincronizar el código clave.
(3) Use variables de dominio especiales (volátiles) para lograr la sincronización de hilos
A. La palabra clave volátil proporciona un mecanismo sin bloqueo para acceder a variables de dominio
b.
c. Por lo tanto, cada vez que usa el campo, debe recalcularlo, en lugar de usar el valor en el registro
d.volatil no proporciona ninguna operación atómica, ni se puede utilizar para modificar variables del tipo final
El código de Bank.Java es el siguiente:
paquete Threadtest; (System.CurrentTimemillis () + "Save:" + Money); ; " + recuento);}}
¿Cómo es el efecto de operación?
Saldo insuficiente Saldo de la cuenta: 0
Saldo insuficiente Saldo de la cuenta: 100
1441792010959 Saved: 100
Saldo de la cuenta: 100
1441792011960 Take Out: 100
Saldo de la cuenta: 0
1441792011961 Saved: 100
Saldo de la cuenta: 100
¿Es porque no puedo entenderlo de nuevo y está desordenado de nuevo? ¿Por qué es esto? Se debe a que volátil no puede garantizar operaciones atómicas, por lo que volátil no puede reemplazar sincronizado. Además, Volatile organizará el compilador para optimizar el código, por lo que si puede usarlo, no se aplicará. Su principio es que cada vez que un hilo quiere acceder a una variable modificada por Volátil, se lee desde la memoria, en lugar de en el caché, por lo que el valor variable accedido por cada subproceso es el mismo. Esto asegura la sincronización.
(4) Use el bloqueo de reingreso para lograr la sincronización de subprocesos
Se ha agregado un nuevo paquete java.util.concurrent a Javase5.0 para admitir la sincronización. La clase Reentrantlock es un bloqueo reentrante y mutuamente excluyente que implementa la interfaz de bloqueo.
Los métodos comunes de la clase Reenreantlock son:
Reentrantlock (): cree una instancia de reentrantlock
bloqueo (): obtenga el bloqueo
Desbloquear (): Reentrantlock Nota: Reentrantlock () también tiene un constructor que puede crear bloqueos justos, pero no se recomienda usarlo porque puede reducir en gran medida la eficiencia de ejecución del programa.
El código Bank.Java se modifica de la siguiente manera:
paquete Threadtest; //Necesita declarar este bloqueo de bloqueo privado = nuevo reentrantlock (); tln (System .CurrentTimemillis () + "Save:" + Money); if (count - Money <0) {System.out.println ("Balance insuficiente"); ;
¿Cómo es el efecto de operación?
Saldo insuficiente Saldo de la cuenta: 0
Saldo insuficiente Saldo de la cuenta: 0
1441792891934 Depósito: 100
Saldo de la cuenta: 100
1441792892935 Saved: 100
Saldo de la cuenta: 200
1441792892954 Take Out: 100
Saldo de la cuenta: 100
El efecto es similar a los dos primeros métodos.
Si la palabra clave sincronizada puede satisfacer las necesidades de los usuarios, use sincronizado porque puede simplificar el código. Si necesita funciones más avanzadas, use la clase Reentrantlock.
(5) Use variables locales para lograr la sincronización de hilos
El código de Bank.Java es el siguiente:
paquete ThreadTest; / ** * @author ww * * / public class Bank {private static threadlocal <integer> count = new ThreadLocal <Integer> () {@Override P Integer rotado InitialValue () {// TODO Auto Generado Stub regreso 0; ); ()- Money); cuento.
Efecto de ejecución:
Saldo insuficiente Saldo de la cuenta: 0
Saldo insuficiente Saldo de la cuenta: 0
1441794247939 Saved: 100
Saldo de la cuenta: 100
Equilibrio insuficiente
1441794248940 Save: 100
Saldo de la cuenta: 0
Saldo de la cuenta: 200
Saldo insuficiente Saldo de la cuenta: 0
14417942499941 Saved: 100
Saldo de la cuenta: 300
Después de ver el efecto de la operación, estaba confundido al principio. Eche un vistazo al principio de ThreadLocal:
Si usa ThreadLocal para administrar variables, cada hilo que usa la variable obtendrá una copia de la variable, y las copias son independientes entre sí, para que cada hilo pueda modificar su propia copia de la variable a voluntad sin afectar otros hilos. Ahora entiendo. Entonces ocurrirá el efecto anterior.
Mecanismo de hilos y sincronización
A. Los mecanismos de sincronización y threadlocal están destinados a resolver el problema de conflicto de acceso de la misma variable en múltiples lecturas
b.
Ahora lo entiendo. Cada uno tiene sus propias ventajas y desventajas y tiene sus escenarios aplicables.