Cet article effectue une analyse comparative de Lock synchronisé au nouveau StampedLock dans Java8. Les amis intéressés par les nouvelles fonctionnalités de Java8, StampedLock, devraient y jeter un œil ensemble
Java8 est comme un trésor, une petite amélioration de l'API suffit pour écrire un article, comme la synchronisation, qui a toujours été un vieux sujet dans la programmation simultanée multithread Je pense que personne n'aime le code synchronisé, ce qui réduira le débit et d'autres indicateurs de performance de. l'application, et finalement lorsqu'elle est mauvaise, elle se bloque et plante, mais même dans ce cas, vous n'avez pas le choix car vous devez garantir l'exactitude des informations. Par conséquent, cet article a décidé de mener une analyse comparative de Lock synchronisé au nouveau StampedLock en Java 8. Je pense que StampedLock ne décevra pas tout le monde.
synchronisé
Avant Java5, la synchronisation était principalement implémentée à l'aide de synchronisé. C'est un mot-clé du langage Java Lorsqu'il est utilisé pour modifier une méthode ou un bloc de code, il peut garantir qu'au plus un thread exécute le code en même temps.Il existe quatre blocs de synchronisation différents :
1. Méthode d'instance 2. Méthode statique 3. block in 4. Bloc synchronisé dans la méthode statique Tout le monde devrait être familier avec cela, je n'entrerai donc pas dans plus de détails. Ce qui suit est un exemple de code .
synchronized(this) // do operation }
Verrouillage
Il est ajouté par Java 5 dans java.util.concurrent.locks et API.
Lock est une interface. Les méthodes de base sont lock(), unlock() et tryLock(). Les classes d'implémentation incluent ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock; >ReentrantReadWriteLock, ReentrantLock et les verrous synchronisés ont la même sémantique de mémoire.
Différent de synchronisé, Lock est entièrement écrit en Java et n'a rien à voir avec l'implémentation de la JVM au niveau Java. Lock fournit un mécanisme de verrouillage plus flexible et de nombreuses fonctionnalités que la synchronisation ne fournit pas, telles que le vote de verrouillage, l'attente de verrouillage chronométrée et l'attente de verrouillage d'interruption, mais comme le verrouillage est implémenté via du code, pour garantir que le verrou sera libéré, unLock( ) into then{}
Ce qui suit est un exemple de code de Lock
Résumé : Plus flexible et évolutif que le mécanisme de verrouillage synchronisé, mais de toute façon synchronisé le code est plus facile à écrire
rwlock.writeLock().lock(); try { // do operation } finally { rwlock.writeLock().unlock(); }
StampedLock
C'est java8 dans java.util.concurrent .locks est une nouvelle API.
ReentrantReadWriteLock ne peut obtenir le verrou en écriture que lorsqu'il n'y a pas de verrou en lecture-écriture. Cela peut être utilisé pour implémenter une lecture pessimiste (lecture pessimiste), c'est-à-dire que si la lecture est effectuée pendant l'exécution, il peut y avoir une lecture pessimiste. souvent une autre implémentation doit écrire, afin de maintenir la synchronisation, le verrou en lecture de ReentrantReadWriteLock peut s'avérer utile.
Le verrou de contrôle StampedLock a trois modes (écriture, lecture, lecture optimiste). Un état StampedLock est composé de deux parties : version et mode. La méthode d'acquisition du verrou renvoie un numéro comme tampon de ticket, qui utilise le correspondant. état de verrouillage Indique et contrôle l'accès, et le chiffre 0 indique qu'aucun verrou en écriture n'est autorisé pour l'accès. Les verrous de lecture sont divisés en verrous pessimistes et verrous optimistes.
lancer une exception
) , cette petite amélioration peut grandement améliorer le débit du programme ! !
Ce qui suit est un exemple de StampedLock fourni par java doc
class Point { private double x, y; private final StampedLock sl = new StampedLock(); void move(double deltaX, double deltaY) { // an exclusively locked method long stamp = sl.writeLock(); try { x += deltaX; y += deltaY; } finally { sl.unlockWrite(stamp); } } //下面看看乐观读锁案例 double distanceFromOrigin() { // A read-only method long stamp = sl.tryOptimisticRead(); //获得一个乐观读锁 double currentX = x, currentY = y; //将两个字段读入本地局部变量 if (!sl.validate(stamp)) { //检查发出乐观读锁后同时是否有其他写锁发生? stamp = sl.readLock(); //如果没有,我们再次获得一个读悲观锁 try { currentX = x; // 将两个字段读入本地局部变量 currentY = y; // 将两个字段读入本地局部变量 } finally { sl.unlockRead(stamp); } } return Math.sqrt(currentX * currentX + currentY * currentY); } //下面是悲观读锁案例 void moveIfAtOrigin(double newX, double newY) { // upgrade // Could instead start with optimistic, not read mode long stamp = sl.readLock(); try { while (x == 0.0 && y == 0.0) { //循环,检查当前状态是否符合 long ws = sl.tryConvertToWriteLock(stamp); //将读锁转为写锁 if (ws != 0L) { //这是确认转为写锁是否成功 stamp = ws; //如果成功 替换票据 x = newX; //进行状态改变 y = newY; //进行状态改变 break; } else { //如果不能成功转换为写锁 sl.unlockRead(stamp); //我们显式释放读锁 stamp = sl.writeLock(); //显式直接进行写锁 然后再通过循环再试 } } } finally { sl.unlock(stamp); //释放读锁或写锁 } } }
StampedLock est moins cher que ReentrantReadWriteLock, ce qui signifie qu'il consomme moins.
Comparaison des performances entre StampedLock et ReadWriteLock
L'image ci-dessous montre que par rapport à ReadWritLock, dans le cas d'un seul thread, la vitesse de lecture est environ 4 fois, l'écriture est 1x.
L'image ci-dessous montre qu'avec six threads, les performances de lecture sont des dizaines de fois, et les performances d'écriture sont également près de 10 fois : La figure suivante montre l'amélioration du débit :Résumé
1. Synchronisé est implémenté au niveau de la JVM. Non seulement la synchronisation peut être surveillée via une certaine surveillance. les outils se verrouillent, et si une exception se produit lors de l'exécution du code, la JVM libérera automatiquement le verrou
2. Assurez-vous que ReentrantReadWriteLock et StampedLock sont tous des verrous au niveau de l' objet . que le verrou sera Pour libérer, vous devez mettre unLock() dans final{};
3. StampedLock a une énorme amélioration du débit, en particulier dans les scénarios où il y a de plus en plus de threads de lecture
.4. StampedLock possède une API complexe. Pour les opérations de verrouillage, il est facile d'abuser d'autres méthodes ;
5 Lorsqu'il n'y a que quelques concurrents, synchronisé est une bonne implémentation de verrouillage à usage général ;
6. Lorsque la croissance des threads peut être estimée, ReentrantLock est une bonne implémentation de verrouillage à usage général ;
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!