1. Problema sincrónico planteado
La sincronización de hilos es evitar daños a los datos cuando múltiples subprocesos acceden a un objeto de datos.
Por ejemplo: tanto Threads Thinda como Threadb operan el mismo objeto FOO y modifican los datos en el objeto FOO.
paquete cn.thread; public class foo {private int x = 100; public int getx () {return x; } public int Fix (int y) {x = x - y; regresar x; }} paquete cn.thread; public class Myrunnable Implements Runnable {private foo foo = new foo (); public static void main (string [] args) {myrunnable run = new Myrunnable (); Hilo ta = nuevo hilo (ejecutar, "Thread-A"); Hilo tb = nuevo hilo (ejecutar, "hilo-b"); ta.Start (); tb.start (); } public void run () {for (int i = 0; i <3; i ++) {this.fix (30); intente {Thread.sleep (1); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println (thread.currentThread (). GetName () + ": el valor x del objeto foo actual =" + foo.getx ()); }} public int Fix (int y) {return foo.fix (y); }}Resultados de ejecución:
Thread-B: el valor x del objeto Foo actual = 40
Thread-A: el valor x del objeto Foo actual = 40
Thread -B: El valor x del objeto FOO actual = -20
Thread -A: el valor x del objeto FOO actual = -20
Thread -B: El valor x del objeto FOO actual = -80
Thread -A: el valor x del objeto Foo actual = -80
De los resultados, se descubrió que dicho valor de salida era obviamente irrazonable. La razón es que dos hilos acceden a objetos FOO sin control y modifican sus datos.
Si desea mantener la racionalidad de los resultados, solo necesita lograr un objetivo, que es restringir el acceso a Foo, y solo un hilo puede acceder a él a la vez. Esto garantizará la racionalidad de los datos en el objeto FOO.
En el código Java específico, se deben completar dos operaciones:
Identifique la variable FOO X de la clase de recursos que es visitada por la competencia como privada;
Sincronice el código que modifica las variables y use la palabra clave sincronizada para sincronizar el método o código.
paquete cn.thread; public class foo2 {private int x = 100; public int getx () {return x; } // método sincronizado público sincronizado int fix (int y) {x = x - y; System.out.println ("Thread" + Thread.CurrentThread (). GetName () + "Ejecutar los extremos, reducir" " + y +" ", el valor actual es:" + x); regresar x; } // // bloque de código sincronizado // public int fix (int y) {// sincronizado (this) {// x = x - y; // system.out.println ("hilo" + thread.currentThread (). GetName () + "ejecutar termina", reduzca " + y /// +" ", el valor actual es:" + x); ///} // // return final paquete cn.thread; public class myrunnable2 {public static void main (string [] args) {myrunnable2 run = new MyRunnable2 (); Foo2 foo2 = new foo2 (); Mythread t1 = run.new mythread ("hilo A", foo2, 10); Mythread t2 = run.new mythread ("hilo b", foo2, -2); Mythread t3 = run.new mythread ("hilo c", foo2, -3); Mythread t4 = run.new mythread ("hilo d", foo2, 5); t1.start (); t2.start (); t3.start (); t4.Start (); } class myThread extiende el hilo {privado foo2 foo2; / ** Valor actual*/ private int y = 0; Mythread (nombre de cadena, foo2 foo2, int y) {super (nombre); this.foo2 = foo2; this.y = y; } public void run () {foo2.fix (y); }}} El subproceso de la ejecución termina, reduce "10", el valor actual es: 90
El hilo C ejecuta y termina, reduce "-3", el valor actual es: 93
El hilo B se ejecuta al final, reduce "-2", el valor actual es: 95
El subproceso D se ejecuta y termina, reduce "5", el valor actual es: 90
2. Sincronización y bloqueo
1. El principio del bloqueo
Cada objeto en Java tiene un bloqueo incorporado.
Cuando el programa se ejecuta en un método de sincronización sincronizado no estático, el bloqueo asociado con la instancia actual de la clase de código que se está ejecutando (esta instancia). Un bloqueo que adquiere un objeto también se llama adquirir bloqueo, bloquear un objeto, bloquear un objeto o sincronizar un objeto.
El bloqueo de objetos solo funciona cuando el programa se ejecuta a un método de sincronización o bloque de código sincronizado.
Solo hay un bloqueo para un objeto. Entonces, si un hilo adquiere el bloqueo, ningún otro hilo puede adquirir el bloqueo hasta que el primer subproceso se libera (o regresa) el bloqueo. Esto también significa que ningún otro hilo puede ingresar el método o bloque de código sincronizado en el objeto hasta que se libera el bloqueo.
Liberar un bloqueo significa que el hilo de bloqueo sale del método de sincronización o bloque de código sincronizado.
Hay algunos puntos clave sobre el bloqueo y la sincronización:
1) Solo se pueden sincronizar los métodos, pero las variables y las clases no se pueden sincronizar;
2) Cada objeto tiene solo un bloqueo; Cuando se trata de sincronización, ¿qué debería estar claro? Es decir, ¿en qué objeto está sincronizado?
3) No hay necesidad de sincronizar todos los métodos de la clase. Las clases pueden tener métodos síncronos y asincrónicos.
4) Si dos hilos quieren ejecutar el método sincronizado en una clase, y los dos subprocesos usan la misma instancia para llamar al método, solo un hilo puede ejecutar el método a la vez, y el otro debe esperar hasta que se libere el bloqueo. Es decir: si un hilo adquiere un bloqueo en un objeto, ningún otro hilo puede ingresar ningún método de sincronización en la clase (de ese objeto).
5) Si el hilo tiene sincronización y métodos asincrónicos, los métodos asíncronos pueden acceder libremente por múltiples hilos sin estar restringidos por bloqueos.
6) Cuando el hilo duerme, no se lanzará ningún bloqueo que contenga.
7) Los hilos pueden obtener múltiples bloqueos. Por ejemplo, llamar al método de sincronización de otro objeto en el método de sincronización de un objeto adquirirá el bloqueo de sincronización de los dos objetos.
8) La sincronización perjudica la concurrencia y debe reducir el rango de sincronización tanto como sea posible. La sincronización no solo puede sincronizar todo el método, sino también sincronizar algunos bloques de código en el método.
9) Al usar bloques de código de sincronización, debe especificar qué objeto sincronizar, es decir, qué bloqueo del objeto se adquirirá. Por ejemplo:
public int Fix (int y) {sincronizado (this) {x = x - y; } return x;} Por supuesto, el método de sincronización también se puede reescribir como un método asincrónico, pero las funciones son exactamente las mismas, por ejemplo:
public sincronizado int getx () {return x ++;} y
public int getx () {sincronizado (this) {return x ++; }}El efecto es exactamente el mismo.
3. Sincronización del método estático
Para sincronizar los métodos estáticos, se necesita un bloqueo para todo el objeto de clase, que es esta clase (xxx.class).
Por ejemplo:
public static sincronizado int setName (name de cadena) {xxx.name = name;}
Equivalente a
public static int setName (name de cadena) {sincronizado (xxx.class) {xxx.name = name; }}4. ¿Qué sucede si el hilo no puede obtener el bloqueo?
Si el hilo intenta ingresar un método sincrónico y su bloqueo ha sido ocupado, el hilo está bloqueado en el objeto. Esencialmente, un hilo ingresa a un grupo del objeto y debe esperar donde debe esperar hasta que se libere su bloqueo y el hilo se vuelve ejecutable o vuelva a ejecutar.
Al considerar el bloqueo, asegúrese de prestar atención a qué objeto se está utilizando para bloquear:
1. Los hilos que llaman métodos de sincronización no estática en el mismo objeto se bloquearán entre sí. Si es un objeto diferente, cada hilo tiene su propio bloqueo de objeto, y los hilos no interfieren entre sí.
2. Los hilos que llaman métodos de sincronización estática en la misma clase se bloquearán entre sí, y todos están bloqueados en el mismo objeto de clase.
3.
4. Para los bloques de código sincronizados, debe ver claramente qué objetos se han utilizado para bloquear (el contenido de los soportes sincronizados después de sincronizado). Los hilos sincronizados en el mismo objeto se bloquearán entre sí, y los hilos bloqueados en diferentes objetos nunca se bloquearán entre sí.
5. ¿Cuándo es la necesidad de sincronizar
Cuando múltiples hilos acceden a datos mutuamente excluyentes (intercambiables) simultáneamente, debe sincronizarse para proteger los datos, asegurando que ambos hilos no los modifiquen y los cambien al mismo tiempo.
Para los datos que se pueden cambiar en campos no estáticos, generalmente se accede a métodos no estatales.
Para los datos que se pueden cambiar en un campo estático, generalmente se accede utilizando un método estático.
El problema se vuelve muy complicado si necesita usar campos estáticos en métodos no estáticos, o llamar a métodos no estáticos en campos estáticos. Ha excedido el alcance del examen SJCP.
6. Categoría de seguridad del hilo
Cuando una clase está bien sincronizada para proteger sus datos, esta clase se llama "Safe".
Incluso para las clases seguras de hilo, debe tener mucho cuidado, porque los hilos que operan aún no son necesariamente seguros.
7. Resumen de sincronización de hilos
1. El propósito de la sincronización de subprocesos es proteger el daño a los recursos cuando múltiples hilos acceden a un recurso.
2. El método de sincronización de hilo se implementa a través de bloqueos. Cada objeto tiene solo un bloqueo. Este bloqueo está asociado con un objeto específico. Una vez que el hilo adquiere el bloqueo del objeto, otros hilos que acceden al objeto ya no pueden acceder a otros métodos de sincronización del objeto.
3. Para los métodos de sincronización estática, los bloqueos son para esta clase, y los objetos de bloqueo son objetos de clase de esta clase. Las cerraduras de los métodos estáticos y no estáticos no interfieren entre sí. Un hilo adquiere un bloqueo y al acceder a un método de sincronización en otro objeto en un método de sincronización, adquiere estos dos bloqueos de objetos.
4. Para la sincronización, es clave ser siempre consciente de qué objeto sincronizar.
5. Al escribir clases seguras de hilos, debe prestar atención siempre a hacer juicios correctos sobre la lógica y la seguridad de múltiples hilos que compiten para acceder a recursos, analizar las operaciones "atómicas" y asegurarse de que otros hilos no puedan acceder a los recursos competitivos durante la operación atómica.
6. Cuando múltiples hilos esperan un bloqueo de objeto, el hilo que no ha obtenido el bloqueo se bloqueará.
7. El punto muerto es causado por hilos que esperan que se bloqueen, y la probabilidad de ocurrencia en realidad es muy pequeña. Si realmente desea escribir un programa de punto muerto, puede que no sea fácil de usar, jaja. Sin embargo, una vez que un programa muere, el programa morirá.
Enlace original: http://www.cnblogs.com/linjiqin/p/3208843.html
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.