当前位置:网站首页>(obligatoire pour les grandes usines) Le Directeur de l'usine reste debout tard pour faire exploser le foie avec une programmation juc Multi - threadée élevée (2) La jeune fille de l'école a été collectée

(obligatoire pour les grandes usines) Le Directeur de l'usine reste debout tard pour faire exploser le foie avec une programmation juc Multi - threadée élevée (2) La jeune fille de l'école a été collectée

2021-10-14 05:05:30 Directeur d'usine Java

(Un must - have pour une grande usine)Le Directeur de l'usine est resté debout tard, le foie a explosé, le Multithreading est élevé et la concurrence estJUCProgrammation(2.)La sœur cadette a collecté

️‍ Bonjour tout le monde,Je suisjavaDirecteur d'usine,Aujourd'hui encore, je vais vous faire l'expérience d'une haute fréquence d'entrevue multithreadée et simultanée!️‍

À propos de l'auteur

  • Présentation de l'auteur

Page d'accueil du blog:Page d'accueil de l'auteur

Introduction:JAVADomaine créateur de haute qualité、Un étudiant de troisième année、Participer à diverses compétitions provinciales pendant l'école、National race,Une série d'honneurs.

Concentre - toi sur moi.:Suivez mon matériel d'apprentissage、Tous les téléchargements de documents sont disponibles,Mise à jour quotidienne des articles,Inspirez - vous en tant queJAVASenior Program singe.

JUCApprendre

15、Rappel asynchrone

Future Conception originale: Modéliser les résultats d'un événement futur !

En fait, c'est l'avant —》Envoyerajax Demande asynchrone à l'arrière - plan

image-20211011181622244

Mais nous l'utilisons habituellement CompletableFuture

(1)Il n'y a pas de valeur de retourrunAsyncRappel asynchrone

package com.zmz.Async;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/** * @ProjectName: Juc * @Package: com.zmz.Async * @ClassName: runAsync * @Author: Zhang shengrui * @Date: 2021/10/11 18:58 * @Version: 1.0 */
public class runAsync {
    
    public static void main(String[] args) throws ExecutionException, InterruptedException
    {
    
        // Lancement Un Demande

        System.out.println(System.currentTimeMillis());
        System.out.println("---------------------");
        CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
    
            // Lancer une tâche asynchrone 
            try {
    
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+".....");
        });
        System.out.println(System.currentTimeMillis());
        System.out.println("------------------------------");
        //Résultats de l'exécution des extrants
        System.out.println(future.get());  //Obtenir les résultats de l'exécution
    }
}

(2)Rappel asynchrone avec valeur de retoursupplyAsync

package com.zmz.Async;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/** * @ProjectName: Juc * @Package: com.zmz.Async * @ClassName: supplyAsync * @Author: Zhang shengrui * @Date: 2021/10/11 19:09 * @Version: 1.0 */
public class supplyAsync {
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
        //Rappel asynchrone avec valeur de retour
        CompletableFuture<Integer> completableFuture=CompletableFuture.supplyAsync(()->{
    
            System.out.println(Thread.currentThread().getName());
            try {
    
                TimeUnit.SECONDS.sleep(2);
                int i=1/0;
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            return 1024;
        });
        System.out.println(completableFuture.whenComplete((t, u) -> {
    
            /*Nous pouvons voirwhenComplete Le programme ci - dessus a deux paramètres ,L'un estt L'un estu T: Ça représente   Résultats normalement retournés ; U: Ça représente   Lancer un message d'erreur inattendu ;  Si une exception se produit ,getVous pouvez obtenirexceptionallyValeur retournée; */
            //success Rappel
            System.out.println("t=>" + t); // Résultats normaux retournés 
            System.out.println("u=>" + u); // Lancer une exception  Message d'erreur
        }).exceptionally((e) -> {
    
            //errorRappel
            System.out.println(e.getMessage());
            return 404;
        }).get());
    }
}

16、JMM(Java Memory Model )

1)Voyons d'abord ce queJMM?

JMM:JAVAModèle de mémoire, Quelque chose qui n'existe pas ,Abstrait,C'est un concept, C'est aussi un Pacte !

À propos deJMM Quelques conventions de synchronisation :

  1. Avant que le thread ne se déverrouille, Les variables partagées doivent être Tout de suite. Retour à la mémoire principale
  2. Avant le verrouillage du fil ,Il faut Lire la mémoire principale La valeur la plus récente dans la mémoire de travail
  3. Le verrouillage et le déverrouillage sont les mêmes

Le fil est divisé en Mémoire de travail、Mémoire principale.

Huit opérations :

Nom Description
Read(Lire) Agit sur la variable mémoire primaire,Il transfère la valeur d'une variable de la mémoire principale à la mémoire de travail du thread,Pour le suiviloadUtilisation de l'action
load(Chargement) Variables agissant sur la mémoire de travail,Il metread L'opération place les variables de la mémoire principale dans la mémoire de travail
Use(Utiliser) Variables agissant sur la mémoire de travail , Il transfère les variables de la mémoire de travail au moteur d'exécution , Chaque fois qu'une machine virtuelle rencontre une valeur qui doit être utilisée dans une variable , Et cette instruction sera utilisée
assign(Affectation) Variables agissant sur la mémoire de travail , Il place une valeur reçue du moteur d'exécution dans une copie variable de la mémoire de travail
store(Stockage) Variables agissant sur la mémoire principale , Il transfère une valeur d'une variable de la mémoire de travail à la mémoire principale , Pour le suivi writeUtiliser
write(Écrire) Variables agissant sur la mémoire principale ,Il metstoreOpération la valeur de la variable obtenue à partir de la mémoire de travail est placée dans la variable de la mémoire principale
lock(Verrouillé.) Variables agissant sur la mémoire principale, Identifier une variable comme un thread exclusif
unlock(Déverrouiller) Variables agissant sur la mémoire principale,Il libère une variable verrouillée,Les variables libérées peuvent être verrouillées par d'autres threads

Fichier sans nom
Insérer la description de l'image ici

Des dispositions correspondantes ont été prises pour huit opérations :

  • Non autoriséreadEtload、storeEtwriteUne opération apparaît seule.Est d'utiliserreadIl fautload,UtiliséstoreIl fautwrite
  • Le thread n'est pas autorisé à jeter son dernier assignFonctionnement, C'est - à - dire après que les données de la variable de travail ont changé , La mémoire principale doit être informée
  • Ne pas autoriser un thread n'aurait pas assign Les données sont synchronisées de la mémoire de travail à la mémoire principale
  • Une nouvelle variable doit naître dans la mémoire principale , La mémoire de travail n'est pas autorisée à utiliser directement une variable non initialisée . Est de mettre en œuvre des variables use、storeAvant l'opération,Doit passerassignEtloadFonctionnement
  • Une variable ne peut être exécutée que par un seul thread en même temps lock.Plusieurs foislockAprès, Le même nombre de unlockPour déverrouiller
  • Si vous faites une variablelockFonctionnement, La valeur de cette variable est effacée de toute la mémoire de travail ,Avant que le moteur d'exécution n'utilise cette variable, Il faut recommencer loadOuassignValeur de la variable d'initialisation de l'action
  • Si une variable n'est pas lock, On ne peut pas unlockFonctionnement.Pas du tout.unlock Une variable verrouillée par un autre thread
  • Pour une variable unlockAvant l'opération, Cette variable doit être synchronisée à la mémoire principale

image-20211011204148313

Problèmes rencontrés Le programme ne sait pas que la valeur dans la mémoire principale a été modifiée !

17、volatile

1)Garantie de visibilité

package com.zmz.JMM;

import java.util.concurrent.TimeUnit;

/** * @ProjectName: Juc * @Package: com.zmz.JMM * @ClassName: JMMdemo01 * @Author: Zhang shengrui * @Date: 2021/10/11 20:43 * @Version: 1.0 */
public class JMMdemo01 {
    
    // Sansvolatile  Le programme est en boucle morte 
    // Plus maintenant.volatile Est une garantie de visibilité 
    private volatile static Integer number = 0;

    public static void main(String[] args) {
    
        //mainThread
        //Sous - thread1
        new Thread(()->{
    
            while (number==0){
    
            }
        }).start();
        try {
    
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
    
            e.printStackTrace();
        }
        //Sous - thread2
        new Thread(()->{
    
            while (number==0){
    
            }

        }).start();
        try {
    
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
    
            e.printStackTrace();
        }
        number=1;
        System.out.println(number);
    }
}

2)L'atomicité n'est pas garantie

Atomicité: Ça veut dire indivisible , Par exemple, un thread APendant la Mission, Je ne peux pas être dérangé , Et ne peut pas être divisé ,Soit ça marche en même temps,Soit ils échouent en même temps.

package com.zmz.JMM;

/** * @ProjectName: Juc * @Package: com.zmz.JMM * @ClassName: JMMdemo02 * @Author: Zhang shengrui * @Date: 2021/10/11 20:46 * @Version: 1.0 */
public class JMMdemo02 {
    
    private static volatile int num = 0;

    public static void add(){
    
        num++;
        //++ Pas une opération atomique,- Oui.2- Oui.~3Actions
    }

    public static void main(String[] args) {
    
        //En théorienumber === 20000

        for (int i = 1; i <= 20; i++) {
    
            new Thread(()->{
    
                for (int j = 1; j <= 1000 ; j++) {
    
                    add();
                }
            }).start();
        }

        while (Thread.activeCount()>2){
    
            //main gc
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+",num="+num);
    }
}

Utiliser des classes atomiques

image-20200812215909271

package com.zmz.JMM;

import java.util.concurrent.atomic.AtomicInteger;

/** * @ProjectName: Juc * @Package: com.zmz.JMM * @ClassName: JMMdemo03 * @Author: Zhang shengrui * @Date: 2021/10/11 21:05 * @Version: 1.0 */
public class JMMdemo03 {
    
    private static volatile AtomicInteger number = new AtomicInteger();

    public static void add(){
    
// number++;
        number.incrementAndGet();  //Au rez - de - chaussée,CAS Atomicité garantie 
    }

    public static void main(String[] args) {
    
        //En théorienumber === 20000

        for (int i = 1; i <= 20; i++) {
    
            new Thread(()->{
    
                for (int j = 1; j <= 1000 ; j++) {
    
                    add();
                }
            }).start();
        }

        while (Thread.activeCount()>2){
    
            //main gc
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+",num="+number);
    }
}

La couche inférieure de ces classes est directement liée au système d'exploitation ! Est de modifier les valeurs en mémoire .

3)Désactiver le réarrangement des commandes

Qu'est - ce que le réarrangement des instructions?

Le programme que nous avons écrit, L'ordinateur ne fonctionne pas comme nous l'avons écrit nous - mêmes

Code source–> Le compilateur optimise le réarrangement –> Le parallélisme des instructions peut également être réarrangé –> Les systèmes de mémoire sont également réarrangés –>Mise en œuvre

Le processeur en cours de réarrangement d'instruction , Les dépendances entre les données seront prises en considération !

int x=2; //1
int y=4; //2
x=x+10;   //3
y=x*x;   //4

// L'ordre d'exécution souhaité est  1_2_3_4  L'ordre d'exécution possible devient 3124 1423
// Ça ne peut pas être  4123? C'est impossible.
1234567

Effets possibles résultats :Prémisse:a b x yCes quatre valeurs Par défaut, tout est0

ThreadA ThreadB
x=a y=b
b=1 a=2

Résultats normaux : x = 0; y =0

ThreadA ThreadB
b=1 a=2
x=a y=b

Peut - être dans le thread AApparaît dans,Exécution en premierb=1,Et ensuitex=a

InB Peut apparaître dans le thread ,Exécution en premiera=2,Et ensuite exécutery=b

Il est donc possible que les résultats soient les suivants :x=4; y=2

volatile Le réarrangement des instructions peut être évité :

volatile Une barrière de mémoire sera ajoutée , Cette barrière de mémoire garantit l'ordre des instructions dans cette barrière .

Barrière de mémoire:CPUDirectives.Action: Assurer la séquence d'exécution d'une opération particulière ; La visibilité de la mémoire peut être garantie pour certaines variables (Tirer parti de ces caractéristiques,C'est garantivolatile Visibilité réalisée )

image-20200812220019582

4)Résumé

  • En raison de la barrière de mémoire , Il est possible d'éviter le réarrangement des commandes
  • L'atomicité n'est pas garantie
  • volatileVisibilité garantie

🥰Questions d'entrevue: Où utilisez - vous le plus cette barrière de mémoire ?

Mode Singleton

18、Mode Singleton

1)Type affamé

package single;

//Le modèle d'un homme affamé
@SuppressWarnings("all")
public class Hungry {
    
	
	private byte[] date1= new byte[1024*1024];
	private byte[] date2= new byte[1024*1024];
	private byte[] date3= new byte[1024*1024];
	private byte[] date4= new byte[1024*1024];
	private Hungry(){
    
		
	}
	private final static Hungry HUNGRY = new Hungry();
	
	public static Hungry getInstance(){
    
		return HUNGRY;
	}
}

2)DCLParesseux

package single;

import java.lang.reflect.Constructor;

//Paresseux
public class LazyMan {
    

	private LazyMan(){
    
		synchronized(LazyMan.class){
    
			throw new RuntimeException(" N'essayez pas de détruire l'exception en utilisant la réflexion ");
		}
// System.out.println(Thread.currentThread().getName()+"ok");
	}
	
	private static  LazyMan lazyMan;
	//Verrouillage à double détection
	public static LazyMan getInstance(){
    
		if (lazyMan==null) {
    
			synchronized (LazyMan.class) {
    
				if (lazyMan==null) {
    
					lazyMan = new LazyMan();
					//Ce n'est pas une opération atomique
					//1.Allouer de l'espace mémoire
					//2.Exécuter la méthode de construction,Initialiser l'objet
					//3. Pointez cet objet vers l'espace 
				}
			}
			
		}
		return lazyMan;
	}
	
	public static void main(String[] args) throws Exception {
    
// LazyMan instance = LazyMan.getInstance();
		Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
		declaredConstructor.setAccessible(true);
		LazyMan instance = declaredConstructor.newInstance();
		LazyMan instance2 = declaredConstructor.newInstance();
		System.out.println(instance);
		System.out.println(instance2);
				for (int i = 0; i < 2; i++) {
    
			new Thread(()->{
    
				LazyMan.getInstance();
			}).start();
		}
	}
}

3)Classe interne statique

package single;

public class Holder {
    
	
	private Holder(){
    }
	
	private static Holder getInstance(){
    
		return InnerClass.HOLDER;
	}
	
	public static class InnerClass {
    
		private static final Holder HOLDER = new Holder();
	}
}

Un seul cas n'est pas sûr , La raison principale est la réflexion .

4)Enumeration

package com.zmz.Singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/** * @ProjectName: Juc * @Package: com.zmz.Singleton * @ClassName: EnumSingle * @Author: Zhang shengrui * @Date: 2021/10/12 20:06 * @Version: 1.0 */
//enum Qu'est - ce que c'est?? enumEn soi.Class Catégorie
public enum EnumSingle {
    
    INSTANCE;
    public EnumSingle getInstance(){
    
        return INSTANCE;
    }
}

class Test{
    
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    
        EnumSingle instance1 = EnumSingle.INSTANCE;
        Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        //java.lang.NoSuchMethodException: com.ogj.single.EnumSingle.<init>()

        EnumSingle instance2 = declaredConstructor.newInstance();
        System.out.println(instance1);
        System.out.println(instance2);
    }
}

image-20211012200746965

Énumérer le code source final de décompilation du type :

public final class EnumSingle extends Enum
{
    

    public static EnumSingle[] values()
    {
    
        return (EnumSingle[])$VALUES.clone();
    }

    public static EnumSingle valueOf(String name)
    {
    
        return (EnumSingle)Enum.valueOf(com/ogj/single/EnumSingle, name);
    }

    private EnumSingle(String s, int i)
    {
    
        super(s, i);
    }

    public EnumSingle getInstance()
    {
    
        return INSTANCE;
    }

    public static final EnumSingle INSTANCE;
    private static final EnumSingle $VALUES[];

    static 
    {
    
        INSTANCE = new EnumSingle("INSTANCE", 0);
        $VALUES = (new EnumSingle[] {
    
            INSTANCE
        });
    }
}

19、Compréhension approfondieCAS

1)Qu'est - ce queCAS?

CAS(Compare And SwapComparer et remplacer), Contient trois valeurs valeur de mémoire courante (V)、 Valeur initiale attendue (A) Et les valeurs à mettre à jour (B), Nous allons d'abord faire une brève introduction, puis un numéro de blog sera présenté séparément .

package com.zmz.CAS;

import java.util.concurrent.atomic.AtomicInteger;

/** * @ProjectName: Juc * @Package: com.zmz.CAS * @ClassName: CasDemo01 * @Author: Zhang shengrui * @Date: 2021/10/12 20:15 * @Version: 1.0 */

public class CasDemo01 {
    
    //CAS : compareAndSet Comparer et échanger
    public static void main(String[] args) {
    
        AtomicInteger atomicInteger = new AtomicInteger(2020);

        //boolean compareAndSet(int expect, int update)
        //Valeur attendue、Mettre à jour les valeurs
        // Si la valeur réelle  Et  Mes attentes sont les mêmes ,Mise à jour
        // Si la valeur réelle  Et  Mes attentes sont différentes , Alors pas de mise à jour 
        System.out.println(atomicInteger.compareAndSet(2020, 2021));
        System.out.println(atomicInteger.get());

        // Parce que la valeur attendue est 2020  La valeur réelle est devenue 2021  Donc la modification échouera 
        //CAS - Oui.CPU Primitifs simultanés pour 
        atomicInteger.getAndIncrement(); //++Fonctionnement
        System.out.println(atomicInteger.compareAndSet(2020, 2021));
        System.out.println(atomicInteger.get());
    }
}

Allons - y.AtomicInteger Regardez le code source ,On peut le découvrir.

image-20211012202420545

image-20211012203519551

2)Résumé

CAS: Comparer les valeurs dans la mémoire de travail actuelle Et Valeur dans la mémoire principale , Si cette valeur est attendue , Alors faites l'opération ! Si ce n'est pas le cas, continuez à tourner , Les serrures à Spin sont utilisées .

Inconvénients:

  • L'atomicité d'une variable partagée ne peut être garantie qu'une seule fois
  • Le cycle peut prendre du temps
  • Il existera ABAQuestions

Qu'est - ce queABAQuestions?( C'est ce qu'on appelle un chat pour un prince )

image-20211012203955069

package com.zmz.CAS;

import java.util.concurrent.atomic.AtomicInteger;

/** * @ProjectName: Juc * @Package: com.zmz.CAS * @ClassName: CasDemo02 * @Author: Zhang shengrui * @Date: 2021/10/12 20:40 * @Version: 1.0 */
public class CasDemo02 {
    
    //CAS : compareAndSet Comparer et échanger
    public static void main(String[] args) {
    
        AtomicInteger atomicInteger = new AtomicInteger(2020);

        System.out.println(atomicInteger.compareAndSet(2020, 2021));
        System.out.println(atomicInteger.get());

        //boolean compareAndSet(int expect, int update)
        //Valeur attendue、Mettre à jour les valeurs
        // Si la valeur réelle  Et  Mes attentes sont les mêmes ,Mise à jour
        // Si la valeur réelle  Et  Mes attentes sont différentes , Alors pas de mise à jour 
        System.out.println(atomicInteger.compareAndSet(2021, 2020));
        System.out.println(atomicInteger.get());

        // Parce que la valeur attendue est 2020  La valeur réelle est devenue 2021  Donc la modification échouera 
        //CAS - Oui.CPU Primitifs simultanés pour 
// atomicInteger.getAndIncrement(); //++Fonctionnement
        System.out.println(atomicInteger.compareAndSet(2020, 2021));
        System.out.println(atomicInteger.get());
    }
}

20、Référence atomique

Pour résoudreABAQuestions, La pensée correspondante :Est d'utiliserLa serrure optimiste~

Attention!:

Integer Mécanisme de cache d'objets utilisé , La plage par défaut est -128~127, La méthode statique de l'usine est recommandée valueOf Obtenir l'Instance objet ,Au lieu denew,Parce quevalueOfUtiliser le cache,Etnew Un nouvel objet doit être créé pour allouer un nouvel espace mémoire .

Description:PourInteger var = ?In-128 à127Affectation entre,IntegerL'objet estIntegerCache .cacheProduire,Réutilisera les objets existants, Dans cette sectionIntegerLes valeurs peuvent être utilisées directement==Entrez. Jugement d'exécution ,Mais toutes les données en dehors de cet intervalle,Sont produits sur le tas,Les objets existants ne sont pas réutilisés, C'est un grand trou ,RecommandéequalsMéthode de jugement.

package com.zmz.CAS;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/** * @ProjectName: Juc * @Package: com.zmz.CAS * @ClassName: CasDemo03 * @Author: Zhang shengrui * @Date: 2021/10/12 20:45 * @Version: 1.0 */

public class CasDemo03 {
    
    /**AtomicStampedReference Attention!, Si le générique est une classe d'emballage , Notez le problème de référence de l'objet  *  Fonctionnement normal de l'entreprise , Il y a beaucoup d'objets en comparaison  */
    static AtomicStampedReference<Integer> atomicStampedReference = new
            AtomicStampedReference<>(1, 1);

    // CAS compareAndSet : Comparer et échanger!
    public static void main(String[] args) {
    
        new Thread(() -> {
    
            int stamp = atomicStampedReference.getStamp(); // Obtenir le numéro de version
            System.out.println("a1=>" + stamp);

            try {
    
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            //  Lors de la modification de l'opération , Mise à jour du numéro de version  + 1
            atomicStampedReference.compareAndSet(1, 2,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);

            System.out.println("a2=>" + atomicStampedReference.getStamp());
            //  Changez la valeur à nouveau ,  Mise à jour du numéro de version  + 1
            System.out.println(atomicStampedReference.compareAndSet(2, 1,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1));
            System.out.println("a3=>" + atomicStampedReference.getStamp());
        }, "a").start();

        //  Le principe de la serrure optimiste est le même !
        new Thread(() -> {
    
            int stamp = atomicStampedReference.getStamp(); // Obtenir le numéro de version
            System.out.println("b1=>" + stamp);
            try {
    
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            System.out.println(atomicStampedReference.compareAndSet(1, 3,
                    stamp, stamp + 1));
            System.out.println("b2=>" + atomicStampedReference.getStamp());
        }, "b").start();
    }
}

image-20211012204643832

21、 Compréhension des différentes serrures

1)Verrouillage équitable,Serrure injuste

  1. Verrouillage équitable: Une serrure très juste , Pas de files d'attente ,Tu dois venir avant.image-20211012204843218
  2. Serrure injuste: Très injuste. , Autoriser les files d'attente , L'ordre peut être modifié

2)Verrouillage réinscriptible

image-20211012205812027

​ 1.SynchonizedVerrouillage

package com.zmz.lock;

/** * @ProjectName: Juc * @Package: com.zmz.lock * @ClassName: SynchonizedDemo * @Author: Zhang shengrui * @Date: 2021/10/12 20:59 * @Version: 1.0 */
public class SynchonizedDemo {
    
    public static void main(String[] args) {
    
        Phone phone = new Phone();
        new Thread(()->{
    
            phone.sms();
        },"A").start();
        new Thread(()->{
    
            phone.sms();
        },"B").start();
    }

}

class Phone{
    
    public synchronized void sms(){
    
        System.out.println(Thread.currentThread().getName()+"=>  Un court souffle ");
        call();// Il y a aussi une serrure ici 
    }
    public synchronized void call(){
    
        System.out.println(Thread.currentThread().getName()+"=> Appelle");
    }
}

​ 2.LockVerrouillage

package com.zmz.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/** * @ProjectName: Juc * @Package: com.zmz.lock * @ClassName: LockDemo * @Author: Zhang shengrui * @Date: 2021/10/12 21:02 * @Version: 1.0 */
public class LockDemo {
    
    public static void main(String[] args) {
    
        Phone2 phone = new Phone2();
        new Thread(()->{
    
            phone.sms();
        },"A").start();
        new Thread(()->{
    
            phone.sms();
        },"B").start();
    }

}
class Phone2{
    

    Lock lock=new ReentrantLock();

    public void sms(){
    
        lock.lock(); //Détails: Voici deux serrures , Deux clés 
        //lock Les serrures doivent être jumelées , Sinon, il sera bloqué 
        try {
    
            System.out.println(Thread.currentThread().getName()+"=> Envoyer un SMS");
            call();// Il y a aussi une serrure ici 
        } catch (Exception e) {
    
            e.printStackTrace();
        }finally {
    
            lock.unlock();
        }
    }
    public void call(){
    
        lock.lock();
        try {
    
            System.out.println(Thread.currentThread().getName() + "=> Appelle");
        }catch (Exception e){
    
            e.printStackTrace();
        }
        finally {
    
            lock.unlock();
        }
    }
}

Attention!:

  1. lock Les serrures doivent être jumelées ,équivalent àlockEt unlock La quantité doit être la même
  2. La serrure que j'ai mise dehors , Peut également être déverrouillé à l'intérieur ; La serrure à l'intérieur , Il est également possible de déverrouiller à l'extérieur

3)Spin Lock

​ 1.spinlock

public final int getAndAddInt(Object var1, long var2, int var4) {
    
    int var5;
    do {
    
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    return var5;
}

​ 2. Verrouillage de spin auto - conçu

package com.zmz.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

/** * @ProjectName: Juc * @Package: com.zmz.lock * @ClassName: MySpinlockTest * @Author: Zhang shengrui * @Date: 2021/10/12 21:07 * @Version: 1.0 */
class MySpinlock {
    
    // Par défaut
    // int 0
    //thread null
    AtomicReference<Thread> atomicReference=new AtomicReference<>();

    //Verrouillage
    public void myLock(){
    
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName()+"===> mylock");

        //Spin Lock
        while (!atomicReference.compareAndSet(null,thread)){
    
            System.out.println(Thread.currentThread().getName()+" ==>  En spin ~");
        }
    }


    //Déverrouiller
    public void myUnlock(){
    
        Thread thread=Thread.currentThread();
        System.out.println(thread.getName()+"===> myUnlock");
        atomicReference.compareAndSet(thread,null);
    }
}
public class MySpinlockTest {
    
    public static void main(String[] args) throws InterruptedException {
    
        ReentrantLock reentrantLock = new ReentrantLock();
        reentrantLock.lock();
        reentrantLock.unlock();


        //UtiliserCASRéaliser le verrouillage de spin
        MySpinlock spinlockDemo=new MySpinlock();
        new Thread(()->{
    
            spinlockDemo.myLock();
            try {
    
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {
    
                e.printStackTrace();
            } finally {
    
                spinlockDemo.myUnlock();
            }
        },"Thread1").start();

        TimeUnit.SECONDS.sleep(1);


        new Thread(()->{
    
            spinlockDemo.myLock();
            try {
    
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {
    
                e.printStackTrace();
            } finally {
    
                spinlockDemo.myUnlock();
            }
        },"Thread2").start();
    }
}

Résultats des opérations:t2 Le processus doit attendre t1ProcessusUnlockAprès,PourUnlock, Avant cela, faites l'attente de spin .

4)Blocage

image-20211012211214241

package com.zmz.lock;

import java.util.concurrent.TimeUnit;

/** * @ProjectName: Juc * @Package: com.zmz.lock * @ClassName: DeadLockDemo * @Author: Zhang shengrui * @Date: 2021/10/12 21:13 * @Version: 1.0 */
public class DeadLockDemo {
    
    public static void main(String[] args) {
    
        String lockA= "lockA";
        String lockB= "lockB";

        new Thread(new MyThread1(lockA,lockB),"Thread1").start();
        new Thread(new MyThread1(lockB,lockA),"Thread2").start();
    }
}
class MyThread1 implements Runnable{
    

    private String lockA;
    private String lockB;

    public MyThread1(String lockA, String lockB) {
    
        this.lockA = lockA;
        this.lockB = lockB;
    }

    @Override
    public void run() {
    
        synchronized (lockA){
    
            System.out.println(Thread.currentThread().getName()+" lock"+lockA+"===>get"+lockB);
            try {
    
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
            synchronized (lockB){
    
                System.out.println(Thread.currentThread().getName()+" lock"+lockB+"===>get"+lockA);
            }
        }
    }
}

image-20211012211702552

Comment résoudre le problème de l'impasse ?

1、UtiliserjpsLocaliser le numéro de processus,jdkDebinSous la table des matières: Il y a unjps

jps -l

image-20211012211915844

2、 Numéro du processus Message d'impasse trouvé

jstack Numéro du processus	# En cas de refus d'accès   Assurez - vous de fonctionner en tant qu'administrateur 

image-20211012212412718

Informations générales à la fin :

image-20211012212448697

版权声明
本文为[Directeur d'usine Java]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/10/20211013211944071m.html

随机推荐