Verrouiller le partage du résumé d'utilisation
Verrouillage
Dans l'article précédent, nous avons expliqué comment utiliser le mot-clé synchronisé pour obtenir un accès synchrone. Dans cet article, nous continuons à discuter de ce problème. À partir de Java 5, un autre moyen d'obtenir un accès synchrone est fourni dans le package java.util.concurrent.locks, à savoir Lock.
Certains amis peuvent demander, puisque l'accès synchronisé peut être obtenu via la synchronisation, pourquoi devons-nous fournir un verrouillage ? Cette question sera abordée ci-dessous. Cet article commence par les lacunes de synchronisé, puis décrit les classes et interfaces couramment utilisées sous le package java.util.concurrent.locks, et aborde enfin les éléments suivants sur le concept de verrous
Défauts synchronisés
Nous avons dit plus tôt qu'il existe deux situations dans lesquelles un thread synchronisé libère le verrou :
Le bloc de code ou la méthode synchronisée est exécuté
Lorsqu'une exception se produit dans un bloc de code ou une méthode de synchronisation, la jvm libère automatiquement le verrou
Vous pouvez voir sur le verrou de libération synchronisé au-dessus de Out, le verrou ne sera libéré qu'après l'exécution du bloc de code synchronisé ou si une exception se produit. Si le programme dans le bloc de code est bloqué pour des raisons d'E/S, le thread ne sera jamais libéré. le verrou, mais à ce moment-là, d'autres threads exécuteront toujours d'autres programmes, ce qui affecte grandement l'efficacité d'exécution du programme. Nous avons maintenant besoin d'un mécanisme qui puisse empêcher le thread d'attendre indéfiniment et de répondre aux interruptions. lock
De plus, s'il existe un programme qui contient plusieurs threads de lecture et un thread d'écriture, nous pouvons savoir que synchronisé ne peut être exécuté que par un seul thread, mais nous avons besoin de plusieurs threads de lecture. lire en même temps, donc utiliser synchronisé n'est certainement pas possible, mais nous utilisons le verrouillage de la même manière. Cela peut être fait
Verrouillage
En regardant le. API, nous pouvons voir que Lock est une interface, donc les objets ne peuvent pas être créés directement, mais nous pouvons utiliser les classes qu'elle implémente pour créer un objet, ne nous inquiétez pas pour cela, jetons d'abord un coup d'œil aux méthodes implémentées par Lock. class Nous expliquerons l'implémentation spécifique en détail lors de la présentation des classes qu'elle implémente
méthodes
lock()
Obtenez le verrou, sinon. il attendra éternellement
unlock()
Libérez le verrou
tryLock()
Essayez d'acquérir le verrou si le verrou est acquis avec succès, exécutez-le. Si le verrou n'est pas acquis avec succès, alors il n'y aura pas d'attente
lockInterruptibly()
Si le thread actuel n'est pas interrompu, le verrou est acquis.
ReentrantLock
ReentrantLock est un verrou réentrant C'est une classe qui implémente l'interface Lock est un mécanisme d'allocation de threads, réentrant. Cela signifie qu'il est toujours alloué au thread qui a récemment obtenu le verrou. Il s'agit d'un mécanisme d'allocation injuste, et bien sûr, afin de résoudre ce phénomène, la méthode de construction de ReentrantLock fournit également un paramètre équitable . juste est vrai, cela signifie qu'en utilisant le mécanisme d'allocation équitable, le thread avec le temps d'attente le plus long obtiendra le verrou
Méthode de construction
ReentrantLock()
Créer un objet et utiliser le mécanisme réentrant par défaut
ReentrantLock(boolean fair)
Si fair est vrai, alors le mécanisme d'allocation équitable est utilisé
Méthodes courantes
.
lock()
Acquérir le verrou S'il n'est pas acquis, il bloquera toujours
Ce qui suit utilise un programme pour démontrer l'utilisation de la méthode de verrouillage suivante. Le code est le suivant :
//实现接口的线程类public class MyThread implements Runnable {public ReentrantLock rLock = null; //注意这里的锁一定要是全局变量,否则每一个线程都创建一把锁,那么将会毫无意义 public MyThread() {this.rLock = new ReentrantLock(); // 创建默认的可重入锁}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞public void display() {this.rLock.lock(); // 获取锁try {for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "正在输出"+ i); } } finally {this.rLock.unlock(); // 释放锁,注意这步是一定需要的} }@Overridepublic void run() {this.display(); // 调用display方法} }//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象// 下面创建两个线程,并且直接启动,new Thread(thread).start();new Thread(thread).start(); } }
Exécutez le. ci-dessus pour obtenir le résultat comme indiqué ci-dessous :
À partir des résultats ci-dessus, nous pouvons voir que les threads génèrent un par un, et le suivant ne peut être exécuté qu'après avoir attendu la fin de la sortie d'un thread. Un thread, ici est uniquement pour le code entre le verrouillage et le déverrouillage, l'autre code n'est pas contrôlé
Remarque : La création ici peut être répétée. L'objet verrouillé doit être une variable globale pour chaque thread et un objet pouvant être partagé. Si vous créez cet objet dans la méthode d'affichage, cela n'a aucun sens car. chaque thread n'utilise pas du tout le même. Lock
boolean tryLock()
Essayez d'abord d'acquérir le verrou. Si le verrou est acquis, exécutez-le, sinon. cela n'attendra pas éternellement
Utilisez un morceau de code pour essayer la méthode suivante :
//实现接口的线程类public class MyThread implements Runnable {public ReentrantLock rLock = null; // 注意这里的锁一定要是全局变量,否则每一个线程都创建一把锁,那么将会毫无意义public MyThread() {this.rLock = new ReentrantLock(); // 创建默认的可重入锁}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞public void display() {if (this.rLock.tryLock()) // 如果获取了锁{try {for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "正在输出" + i); } } finally {this.rLock.unlock(); // 释放锁,注意这步是一定需要的} } else { System.out.println(Thread.currentThread().getName() + "获取锁失败,我将不会一直等待........"); } }@Overridepublic void run() {this.display(); // 调用display方法} }//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象// 下面创建两个线程,并且直接启动,new Thread(thread).start();new Thread(thread).start(); } }
执行后的Verrouiller le partage du résumé dutilisation如下图:
从上面的Verrouiller le partage du résumé dutilisation我们知道线程0获取了锁开始执行,但是线程1并没有获取锁,但是使用的是tryLock并不是lock,因此不会一直等待下去,所以直接程序向下运行,直接跳过上锁的代码段,因此就输出了上面的那句话后直接结
ReadWriteLock
从API中可以知道,这个也是一个接口,用于实现读写线程,他有两个方法:Lock readLock(),Lock writeLock() 分别用于获得读锁和写锁,指定特定的锁可以实现特定的功能,比如读锁可以在写线程在执行的情况下可以实现多个读线程进行操作,下面我们来介绍它的具体的实现的类ReentrantReadWriteLock
ReentrantReadWriteLock
这个类也是一个可重入分配的类,当然前面已经说过了什么是可重入,现在我们来说说说这个类的详细的用法
构造方法
ReentrantReadWriteLock()
使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock。
ReentrantReadWriteLock(boolean fair)
使用给定的公平策略创建一个新的ReentrantReadWriteLock。
常用的方法
ReentrantReadWriteLock.ReadLock readLock()
用于返回读取操作的锁
前面已经说过读取操作的锁是用来实现多个线程共同执行的,代码如下:
//实现接口的线程类public class MyThread implements Runnable {public ReentrantReadWriteLock rwlock = null;public Lock rLock = null;public MyThread() {this.rwlock = new ReentrantReadWriteLock(); // 创建对象,使用的是非公平的this.rLock = this.rwlock.readLock(); // 获取读取锁对象}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞public void display() {this.rLock.lock(); // 获取读取锁try {for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "正在输出"+ i); } } finally {this.rLock.unlock(); // 释放锁,注意这步是一定需要的} }@Overridepublic void run() {this.display(); // 调用display方法} }//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象// 下面创建两个线程,并且直接启动,for(int i=0;i<5;i++) {new Thread(thread).start(); } } }
执行上面的程序Verrouiller le partage du résumé dutilisation如下:
从上面的Verrouiller le partage du résumé dutilisation可以知道,其实使用读取操作是多个线程同时进行读取的操作,因此一定要小心谨慎的使用,根据自己的需求,一般不能在里面进行修改了,因为出现Verrouiller le partage du résumé dutilisation不准确的Verrouiller le partage du résumé dutilisation,这个就不多说了,相信大家都明白,总之要小心使用
ReentrantReadWriteLock.WriteLock writeLock()
返回用于写入操作的锁
写入操作的锁和读取操作的锁不一样了,因为一次只能允许一个线程执行写入操作。
并且如果一个线程已经占用了读锁,另外一个线程申请写锁将会一直等待线程释放读锁。
如果一个线程已经占用了写锁,另外一个线程申请读锁,那么这个线程将会一直等待线程释放写锁才能执行。
总之意思就是写线程和读线程不能同时执行,但是多个读线程可以同时执行
下面将使用一个程序详细的体会以下读写锁的综合使用,代码如下:
//实现接口的线程类public class MyThread {public ReentrantReadWriteLock rwlock = null;public Lock rLock = null;public Lock wLock = null;public ArrayList<Integer> arrayList = null;public MyThread() {this.rwlock = new ReentrantReadWriteLock(); // 创建对象,使用的是非公平的this.rLock = this.rwlock.readLock(); // 获取读取锁对象arrayList = new ArrayList<>(); // 实例化this.wLock = this.rwlock.writeLock(); // 获取写入锁对象}// 将unlock方法放在finally中确保执行中代码出现异常仍然能够释放锁,否则将会造成其它的线程阻塞// //向arraylist中写入数据public void put() {this.wLock.lock(); // 获取写入锁try {for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "正在执行写入操作,写入" + i);this.arrayList.add(i); } } finally {this.wLock.unlock(); } }// 从arraylist中读取数据,这里只是随机读取使用的是get,并没有做什么修改,因为这仅仅是读取操作,如果进行了修改必须实现同步public void get() {this.rLock.lock(); // 获取读取操作的锁Random random = new Random();if (!arrayList.isEmpty()) {try {for (int i = 0; i < 10; i++) {int index = random.nextInt(this.arrayList.size() - 1);int data = this.arrayList.get(index); System.out.println(Thread.currentThread().getName() + "正在读取数据 " + data); } } finally {this.rLock.unlock(); } } else { System.out.println("ArrayList为空"); } } }//线程的测试类,主要是创建对象启动线程public class Test {public static void main(String[] args) {final MyThread thread = new MyThread(); // 创建对象ArrayList<Thread> arrayList = new ArrayList<>();/* * 创建8个读线程,2个写线程 */for (int i = 0; i < 2; i++) { arrayList.add(new Thread() {@Overridepublic void run() { thread.put(); } }); } for(int i=0;i<8;i++) { arrayList.add(new Thread(){@Overridepublic void run() { thread.get(); } }); } for (Thread t : arrayList) { t.start(); } } }
Verrouiller le partage du résumé dutilisation如下图:
从上面可以看出写入线程都是一个一个执行的,读取线程是一起执行的
注意: 所有的锁对象对于线程来说必须是全局变量,否则毫无意义。读线程只能进行不影响线程安全性的操作,比如不能进行对数据的修改插入,如果想要进行修改的话必须还要使用锁对必要的代码实现同步操作
参考文章
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!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Après Jdk1.5, sous le package java.util.concurrent.locks, il existe un ensemble d'interfaces et de classes qui implémentent la synchronisation des threads. En matière de synchronisation des threads, tout le monde peut penser au mot-clé synchronisé, qui est un mot-clé intégré. mot-clé en Java. Il gère la synchronisation des threads, mais ce mot-clé présente de nombreux défauts et n'est pas très pratique et intuitif à utiliser, donc Lock apparaît ci-dessous, nous allons comparer et expliquer Lock. Habituellement, lorsque nous utilisons le mot-clé synchronisé, nous rencontrerons les problèmes suivants : (1) Incontrôlabilité, impossible de verrouiller et de déverrouiller les verrous à volonté. (2) L'efficacité est relativement faible. Par exemple, nous lisons actuellement deux fichiers simultanément.

1. Fonction (1) La méthode Lock pour acquérir des verrous prend en charge l'interruption, aucune acquisition après un délai d'attente et n'est pas bloquante (2) Elle améliore la sémantique. L'endroit où verrouiller et déverrouiller doit être écrit (3) Le verrouillage explicite du verrou peut nous apporter. Livré avec une bonne flexibilité, mais en même temps, nous devons libérer manuellement le verrou (4) Objet de condition de condition de support (5) Autoriser plusieurs threads de lecture à accéder aux ressources partagées en même temps 2. Utilisation du verrouillage //Obtenir le verrou voidlock() //Si le thread actuel n'a pas été interrompu, acquérir le verrou voidlockInterruptably()//Renvoyer une nouvelle instance de Condition liée à cette instance de Lock ConditionnewCondition()//Lock uniquement lorsqu'il est appelé

Remarque 1. Lock est une interface du package java.util.concurent, qui définit une série de méthodes d'opération de verrouillage. 2. L'interface Lock comprend principalement les classes d'implémentation ReentrantLock, ReentrantReadWriteLock, ReentrantReadWriteLock et WriteLock. Différent de Synchronized, Lock fournit des interfaces associées telles que l'acquisition et la libération de verrous, ce qui le rend plus flexible à utiliser et plus complexe à utiliser. InstanceReentrantReadWriteLocklock=newReentrantReadWriteLock();Lockread

Résumé : Le mot clé synchronisé est fourni en Java pour garantir qu'un seul thread peut accéder au bloc de code synchronisé. Puisque le mot-clé synchronisé a été fourni, pourquoi l'interface Lock est-elle également fournie dans le package Java SDK ? Est-ce une réinvention inutile de la roue ? Aujourd’hui, nous discuterons ensemble de cette question. Le mot-clé synchronisé est fourni en Java pour garantir qu'un seul thread peut accéder au bloc de code synchronisé. Puisque le mot-clé synchronisé a été fourni, pourquoi l'interface Lock est-elle également fournie dans le package Java SDK ? Est-ce une réinvention inutile de la roue ? Aujourd’hui, parlons-en ensemble

1. Les méthodes d'acquisition lock(), tryLock(), tryLock(longtime, TimeUnitunit) et lockInterruptably() sont toutes utilisées pour acquérir des verrous. (1) La méthode lock() est la méthode la plus couramment utilisée pour obtenir des verrous. Si le verrou a été acquis par un autre thread, attendez. (2) La méthode tryLock() a une valeur de retour, ce qui signifie qu'elle est utilisée pour tenter d'acquérir le verrou. Si l'acquisition réussit, elle renvoie vrai. Si l'acquisition échoue (c'est-à-dire que le verrou a été acquis par un autre). thread), il renvoie false, ce qui signifie ceci La méthode retourne immédiatement quoi qu'il arrive. Vous n'attendrez pas là-bas si vous ne parvenez pas à obtenir la serrure. (3) essayezLoc

Problèmes courants dans la pile technologique Java et leurs solutions Lors du développement d'applications Java, nous rencontrons souvent des problèmes, tels que des problèmes de performances, des fuites de mémoire, la sécurité des threads, etc. Cet article présentera quelques problèmes courants et leurs solutions, et donnera des exemples de code correspondants. 1. Problèmes de performances 1.1 Problèmes de performances causés par la création fréquente d'objets La création fréquente d'objets entraînera des déclenchements fréquents de garbage collection, affectant ainsi les performances du programme. La solution consiste à utiliser le pooling d’objets ou la mise en cache pour réutiliser les objets. Exemple de code : //Réutiliser des objets à l'aide d'un pool d'objets

Vérification de la sécurité PHP via Auth0Lock Avec le développement d'Internet, de plus en plus d'applications nécessitent une authentification des utilisateurs et une vérification de sécurité pour protéger la confidentialité des utilisateurs et la sécurité des données. PHP est un langage backend largement utilisé qui offre de nombreuses façons de mettre en œuvre une validation sécurisée. Auth0 est une plateforme d'authentification et d'autorisation populaire qui offre aux développeurs un moyen flexible et sécurisé de mettre en œuvre l'authentification des utilisateurs. Auth0Lock est celui fourni par Auth0

1. D'un point de vue fonctionnel, Lock et Synchronized sont tous deux des outils utilisés en Java pour résoudre les problèmes de sécurité des threads. 2. D'un point de vue fonctionnel, Synchronized est le mot-clé de synchronisation en Java, Lock est l'interface fournie dans le package J.U.C. , et cela L'interface a de nombreuses classes d'implémentation, y compris l'implémentation de verrous réentrants tels que ReentrantLock Synchronized peut contrôler la force du verrou de deux manières. L'une consiste à modifier le mot-clé synchronisé au niveau de la méthode. sur le bloc de code. Vous pouvez utiliser le cycle de vie de l'objet de verrouillage synchronisé pour contrôler la portée du verrou. L'objet de verrouillage est un objet statique ou une paire de classes.
