1. Problème synchrone soulevé
La synchronisation des threads consiste à éviter d'endommager les données lorsque plusieurs threads accèdent à un objet de données.
Par exemple: Threads Threada et Threadb fonctionnent le même objet FOO et modifient les données de l'objet FOO.
package cn.thread; classe publique foo {private int x = 100; public int getX () {return x; } public int fix (int y) {x = x - y; retour x; }} package cn.thread; public class myrunnable implémente runnable {private foo foo = new foo (); public static void main (String [] args) {myrunnable run = new myrunnable (); Thread ta = nouveau thread (run, "thread-a"); Thread tb = nouveau thread (run, "thread-b"); ta.start (); tb.start (); } public void run () {for (int i = 0; i <3; i ++) {this.fix (30); essayez {thread.sleep (1); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println (thread.currentThread (). GetName () + ": la valeur x de l'objet foo actuel =" + foo.getx ()); }} public int fix (int y) {return foo.fix (y); }}Résultats en cours:
Thread-B: la valeur x de l'objet FOO actuel = 40
Thread-a: la valeur x de l'objet FOO actuel = 40
Thread-B: la valeur x de l'objet FOO actuel = -20
Thread-A: la valeur x de l'objet FOO actuel = -20
Thread-B: la valeur x de l'objet FOO actuel = -80
Thread-A: la valeur x de l'objet FOO actuel = -80
D'après les résultats, il a été constaté qu'une telle valeur de sortie était évidemment déraisonnable. La raison en est que deux threads accèdent aux objets FOO sans contrôle et modifient leurs données.
Si vous souhaitez maintenir la rationalité des résultats, vous n'avez qu'à atteindre un seul objectif, qui est de restreindre l'accès à FOO, et un seul fil peut y accéder à la fois. Cela garantira la rationalité des données dans l'objet FOO.
Dans le code Java spécifique, deux opérations doivent être terminées:
Identifiez la variable FOO X de la classe de ressources visitée par la concurrence comme privée;
Synchronisez le code qui modifie les variables et utilisez le mot-clé synchronisé pour synchroniser la méthode ou le code.
package cn.thread; classe publique foo2 {private int x = 100; public int getX () {return x; } // Méthode synchronisée publique synchronisée int fix (int y) {x = x - y; System.out.println ("thread" + thread.currentThread (). GetName () + "Run se termine, réduire" "+ y +" ", la valeur actuelle est:" + x); retour x; } // // Bloc de code synchronisé // public int fix (int y) {// synchronisé (this) {// x = x - y; // system.out.println ("thread" + thread.currentThread (). GetName () + "Run se termine, réduire" "+ y // +" ", la valeur actuelle est:" + x); //} // // package cn.thread; public class myrunnable2 {public static void main (string [] args) {myrunnable2 run = new myrunnable2 (); Foo2 foo2 = new foo2 (); Mythread t1 = run.new mythread ("thread a", foo2, 10); Mythread t2 = run.new mythread ("thread b", foo2, -2); Mythread t3 = run.new mythread ("thread c", foo2, -3); Mythread t4 = run.new mythread ("thread d", foo2, 5); t1.start (); t2.start (); t3.start (); T4.Start (); } class Mythread étend Thread {private foo2 foo2; / ** Valeur actuelle * / private int y = 0; Mythread (nom de chaîne, foo2 foo2, int y) {super (name); this.foo2 = foo2; this.y = y; } public void run () {foo2.fix (y); }}} Le thread d'une course se termine, réduit "10", la valeur actuelle est: 90
Le thread C s'exécute, réduit "-3", la valeur actuelle est: 93
Le thread B fonctionne à la fin, réduit "-2", la valeur actuelle est: 95
Le thread D fonctionne et se termine, réduit "5", la valeur actuelle est: 90
2. Synchronisation et verrouillage
1. Le principe de verrouillage
Chaque objet en Java a un verrou intégré.
Lorsque le programme s'exécute sur une méthode de synchronisation synchronisée non statique, le verrouillage associé à l'instance actuelle de la classe de code en cours d'exécution (cette instance). Un verrou qui acquiert un objet est également appelé acquérir un verrouillage, verrouillage d'un objet, verrouillage sur un objet ou synchronisation sur un objet.
Le verrouillage d'objet ne fonctionne que lorsque le programme s'exécute vers une méthode de synchronisation synchronisée ou un bloc de code.
Il n'y a qu'un seul verrou pour un objet. Donc, si un fil acquiert le verrou, aucun autre fil ne peut acquérir le verrou avant le premier thread libère (ou renvoie) le verrou. Cela signifie également qu'aucun autre thread ne peut entrer la méthode synchronisée ou le bloc de code sur l'objet jusqu'à ce que le verrouillage soit libéré.
La libération d'un verrou signifie que le thread de verrouillage quitte la méthode de synchronisation synchronisée ou le bloc de code.
Il y a quelques points clés sur le verrouillage et la synchronisation:
1) Seules les méthodes peuvent être synchronisées, mais les variables et les classes ne peuvent pas être synchronisées;
2) Chaque objet n'a qu'un seul verrouillage; En ce qui concerne la synchronisation, sur quoi devrait être clair? C'est-à-dire sur quel objet est synchronisé?
3) Il n'est pas nécessaire de synchroniser toutes les méthodes de la classe. Les classes peuvent avoir des méthodes synchrones et asynchrones.
4) Si deux threads souhaitent exécuter la méthode synchronisée dans une classe et que les deux threads utilisent la même instance pour appeler la méthode, alors un seul thread peut exécuter la méthode à la fois et l'autre doit attendre la sortie du verrouillage. Autrement dit: si un thread acquiert un verrou sur un objet, aucun autre thread ne peut entrer dans aucune méthode de synchronisation dans la classe (de cet objet).
5) Si le thread a une synchronisation et des méthodes asynchrones, les méthodes asynchrones peuvent être librement accessibles par plusieurs threads sans être limités par les verrous.
6) Lorsque le fil dormait, aucun verrouillage, il tient, il sera libéré.
7) Les threads peuvent obtenir plusieurs verrous. Par exemple, appeler la méthode de synchronisation d'un autre objet dans la méthode de synchronisation d'un objet acquérira du verrou de synchronisation des deux objets.
8) La synchronisation altère la concurrence et doit réduire autant que possible la plage de synchronisation. La synchronisation peut non seulement synchroniser la méthode entière, mais aussi synchroniser certains blocs de code dans la méthode.
9) Lorsque vous utilisez des blocs de code de synchronisation, vous devez spécifier l'objet à synchroniser, c'est-à-dire que le verrou de l'objet doit être acquis. Par exemple:
public int fix (int y) {synchronisé (this) {x = x - y; } return x;} Bien sûr, la méthode de synchronisation peut également être réécrite comme une méthode asynchrone, mais les fonctions sont exactement les mêmes, par exemple:
public synchronisé int getX () {return x ++;} et
public int getX () {synchronisé (this) {return x ++; }}L'effet est exactement le même.
3. Synchronisation de la méthode statique
Pour synchroniser les méthodes statiques, un verrou est nécessaire pour l'objet de classe entier, qui est cette classe (xxx.class).
Par exemple:
public static synchronisé int setName (nom de chaîne) {xxx.name = name;}
Équivalent à
public static int setName (string name) {synchronisé (xxx.class) {xxx.name = name; }}4. Que se passe-t-il si le fil ne peut pas obtenir le verrouillage
Si le thread essaie d'entrer une méthode synchrone et que son verrou a été occupé, le thread est bloqué sur l'objet. Essentiellement, un fil entre dans un pool de l'objet et doit attendre où il doit attendre que son verrou est libéré et que le fil redevable ou exécute à nouveau.
Lorsque vous envisagez le blocage, assurez-vous de prêter attention à l'objet utilisé pour le verrouillage:
1. Les threads qui appellent les méthodes de synchronisation non statiques dans le même objet se bloqueront mutuellement. S'il s'agit d'un objet différent, chaque thread a son propre verrouillage d'objet et les threads n'interfèrent pas les uns avec les autres.
2. Les threads qui appellent des méthodes de synchronisation statiques dans la même classe se bloqueront, et ils sont tous verrouillés sur le même objet de classe.
3. Les méthodes de synchronisation statique et les méthodes de synchronisation non statiques ne se bloqueront jamais, car les méthodes statiques sont verrouillées sur des objets de classe, tandis que les méthodes non statiques sont verrouillées sur les objets de cette classe.
4. Pour les blocs de code synchronisés, vous devez voir clairement quels objets ont été utilisés pour le verrouillage (le contenu des supports synchronisés après synchronisé). Les threads synchronisés sur le même objet se bloqueront et les threads verrouillés sur différents objets ne se bloqueront jamais.
5. Quand est la nécessité de synchroniser
Lorsque plusieurs threads accèdent simultanément aux données mutuellement exclusives (échangeables), elles doivent être synchronisées pour protéger les données, garantissant que les deux threads ne le modifient pas et ne les modifient pas en même temps.
Pour les données qui peuvent être modifiées dans des champs non statiques, les méthodes non statiques sont généralement accessibles.
Pour les données qui peuvent être modifiées dans un champ statique, il est généralement accessible en utilisant une méthode statique.
Le problème devient très compliqué si vous avez besoin d'utiliser des champs statiques dans des méthodes non statiques ou d'appeler des méthodes non statiques dans des champs statiques. Il a dépassé la portée de l'examen SJCP.
6. Catégorie de sécurité de fil
Lorsqu'une classe est bien synchronisée pour protéger ses données, cette classe est appelée "mire-safe".
Même pour les cours de filetage, vous devez être très prudent, car les fils qui fonctionnent ne sont pas nécessairement sûrs.
7. Résumé de la synchronisation du thread
1. Le but de la synchronisation du thread est de protéger les dommages aux ressources lorsque plusieurs threads accèdent à une ressource.
2. La méthode de synchronisation du thread est implémentée via les verrous. Chaque objet n'a qu'une seule serrure. Ce verrou est associé à un objet spécifique. Une fois que le thread acquiert le verrouillage de l'objet, d'autres threads accès à l'objet ne peuvent plus accéder à d'autres méthodes de synchronisation de l'objet.
3. Pour les méthodes de synchronisation statique, les verrous sont pour cette classe et les objets de verrouillage sont des objets de classe de cette classe. Les serrures des méthodes statiques et non statiques n'interfèrent pas entre elles. Un thread acquiert un verrou et lors de l'accès à une méthode de synchronisation sur un autre objet dans une méthode de synchronisation, il acquiert ces deux serrures d'objet.
4. Pour la synchronisation, il est essentiel d'être toujours conscient de l'objet à synchroniser.
5. Lors de la rédaction de classes en filetage, vous devez toujours prêter attention à porter des jugements corrects sur la logique et la sécurité de plusieurs threads en concurrence pour accéder aux ressources, analyser les opérations "atomiques" et vous assurer que d'autres threads ne peuvent pas accéder aux ressources concurrentes pendant l'opération atomique.
6. Lorsque plusieurs threads attendent un verrou d'objet, le fil qui n'a pas obtenu le verrouillage se bloquera.
7. L'impasse est causée par des fils qui s'attendent à se verrouiller, et la probabilité d'occurrence en réalité est très faible. Si vous voulez vraiment écrire un programme de blocage, ce n'est peut-être pas facile, haha. Cependant, une fois qu'un programme sera décédé, le programme mourra.
Lien original: http://www.cnblogs.com/linjiqin/p/3208843.html
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.