Maison  >  Article  >  Java  >  Comment implémenter la synchronisation des threads en Java

Comment implémenter la synchronisation des threads en Java

王林
王林original
2019-12-03 16:18:063378parcourir

Comment implémenter la synchronisation des threads en Java

Méthode 1 : utilisez le mot-clé synchronisé

Étant donné que chaque objet en Java a un verrou intégré, lorsque vous utilisez ce mot-clé pour modifier le méthode , un verrou intégré protège l’ensemble de la méthode. Avant d'appeler cette méthode, vous devez obtenir le verrou intégré, sinon il sera bloqué.

Remarque : le mot-clé synchronisé peut également modifier les méthodes statiques. Si la méthode statique est appelée à ce moment, la classe entière sera verrouillée.

Remarque : La synchronisation est une opération très coûteuse, le contenu synchronisé doit donc être minimisé. Habituellement, il n'est pas nécessaire de synchroniser l'intégralité de la méthode, utilisez simplement des blocs de code synchronisés pour synchroniser le code clé.

Le mot-clé synchronisé est utilisé pour protéger les données partagées. Veuillez faire attention aux "données partagées", vous devez distinguer quelles données sont des données partagées

Recommandations du didacticiel vidéo associé : vidéo Java

Exemple :

package com.gcc.interview.synchro;
public class MybanRunnable implements Runnable{
	private Bank bank;
	public MybanRunnable(Bank bank) {
		this.bank = bank;
	}
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			bank.save1(100);
			System.out.println("账户余额是---"+bank.getAccount());
		}
	}
}
rrree

Méthode 2 : attendre et notifier

wait() : met un thread dans un état d'attente et libère le verrou de l'objet qu'il détient.

sleep() : met un thread en cours d'exécution en état de veille. C'est une méthode statique. Appelez cette méthode pour intercepter InterruptedException.

notify() : Réveillez un thread en état d'attente. Notez que lorsque vous appelez cette méthode, vous ne pouvez pas réveiller exactement un thread en état d'attente. Au lieu de cela, la JVM détermine quel thread réveiller. Pas par priorité.

Allnotity() : Réveillez tous les threads en attente. Notez que vous ne donnez pas à tous les threads réveillés un verrou d'objet, mais que vous les laissez entrer en compétition.

Méthode 3 : utiliser des variables de domaine spéciales volatiles pour obtenir la synchronisation des threads

un mot-clé.volatile fournit un mécanisme sans verrouillage pour l'accès aux variables de domaine

b. Utiliser volatile pour modifier un champ équivaut à indiquer à la machine virtuelle que le champ peut être mis à jour par d'autres threads

c Par conséquent, chaque fois que le champ est utilisé, il doit être recalculé au lieu d'utiliser la valeur. dans le registre

d.volatile ne fournit aucune opération atomique, et ne peut pas non plus être utilisé pour modifier les variables de type final

Par exemple :

Dans l'exemple ci-dessus, juste ajouter devant le compte Une modification volatile peut réaliser la synchronisation des threads.

package com.gcc.interview.synchro;
class Bank{
	private int account = 100;
	
	public int getAccount() {
		return account;
	}
	//同步方法
	public synchronized void save(int money) {
		account+=money;
	}
	public void save1(int money) {
		//同步代码块
		synchronized(this) {
			account+=money;
		}
	}
	public void userThread() {
		Bank bank = new Bank();
		MybanRunnable my1 = new MybanRunnable(bank);
		System.out.println("线程1");
		Thread th1 = new Thread(my1);
		th1.start();
		System.out.println("线程2");
		Thread th2 = new Thread(my1);
		th2.start();
	}
}

Remarque : Le problème de non-synchronisation en multi-threading se produit principalement lors de la lecture et de l'écriture sur le domaine. Si le domaine lui-même évite ce problème, il n'est pas nécessaire de modifier la méthode de fonctionnement du domaine. L'utilisation de champs finaux, de champs protégés par verrouillage et de champs volatiles peut éviter les problèmes de non-synchronisation.

Méthode 4 : Utiliser des verrous de réentrance pour réaliser la synchronisation des threads

Un nouveau package java.util.concurrent a été ajouté dans JavaSE5.0 pour prendre en charge la synchronisation.

La classe ReentrantLock est un verrou réentrant et mutuellement exclusif qui implémente l'interface Lock. Il a le même comportement de base et la même sémantique que l'utilisation de méthodes et de blocs synchronisés, et étend ses capacités.

Les méthodes courantes de la classe ReenreantLock sont :

Comment implémenter la synchronisation des threads en Java

Remarque : ReentrantLock() a également une méthode de construction qui peut créer un verrou équitable, mais parce qu'elle peut être considérablement réduit Efficacité d'exécution du programme, non recommandé

//只给出要修改的代码,其余代码与上同
        class Bank {
            //需要同步的变量加上volatile
            private volatile int account = 100;
            public int getAccount() {
                return account;
            }
            //这里不再需要synchronized 
            public void save(int money) {
                account += money;
            }
        }

Remarque : Concernant la sélection de l'objet Lock et du mot-clé synchronisé :

a Il est préférable de ne pas utiliser l'un ou l'autre et d'utiliser un java.util. Package .concurrent Le mécanisme fourni peut aider les utilisateurs à gérer tous les codes liés au verrouillage.

b. Si le mot-clé synchronisé peut répondre aux besoins des utilisateurs, utilisez synchronisé, car il peut simplifier le code

c Si vous avez besoin de fonctions plus avancées, utilisez la classe ReentrantLock. time, Faites attention à libérer le verrou à temps, sinon un blocage se produira généralement dans le code final

Méthode 5 : utiliser des variables locales pour réaliser la synchronisation des threads

Si vous utilisez ThreadLocal pour gérer les variables, alors chaque thread utilisant la variable obtient une copie de la variable, et les copies sont indépendantes les unes des autres, de sorte que chaque thread peut modifier sa propre copie de la variable à volonté sans affecter les autres. fils.

Méthodes courantes de la classe ThreadLocal

Comment implémenter la synchronisation des threads en Java

	private int account = 100;
	private ReentrantLock lock = new ReentrantLock();
	public int getAccount() {
		return account;
	}
	//同步方法
	public  void save(int money) {
		lock.lock();
		try {
			account+=money;
		} finally {
			lock.unlock();
		}
		
	}

Remarque : ThreadLocal et le mécanisme de synchronisation

a.ThreadLocal et le mécanisme de synchronisation sont tous deux destinés à résoudre plusieurs problèmes Problème de conflit d'accès de la même variable dans les threads.

b. Le premier adopte la méthode « d'échange d'espace contre du temps », tandis que le second adopte la méthode d'« échange de temps contre de l'espace ».

Articles et tutoriels connexes recommandés : Démarrer avec zéro base de Java

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn