Maison  >  Article  >  Java  >  Interprétation des nouvelles fonctionnalités de Java 8--StampedLock

Interprétation des nouvelles fonctionnalités de Java 8--StampedLock

零下一度
零下一度original
2017-06-17 14:15:031366parcourir

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
}
Résumé : Synchronized a toujours été un rôle vétéran dans la programmation simultanée multithread. Beaucoup de gens l'appelleront un verrou lourd. Cependant, avec diverses optimisations de Synchronized dans Java SE1.6, Les performances ont également été améliorées.


Verrouillage

Il est ajouté par Java 5 dans java.util.con

current.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.


Cependant, s'il y a beaucoup de lectures et peu d'écritures, l'utilisation de ReentrantReadWriteLock peut entraîner un problème de famine pour le fil d'écriture, c'est-à-dire que le fil d'écriture ne peut pas rivaliser en attendant d'être verrouillé.


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.

Le mode de lecture dit optimiste, c'est-à-dire que s'il y a beaucoup d'opérations de lecture et peu d'opérations d'écriture, vous pouvez être optimiste sur le fait que la probabilité que l'écriture et la lecture se produisent en même temps est très faible , donc utilisez le verrouillage complet en lecture sans pessimisme. Le programme peut vérifier si les données ont été modifiées en écrivant après avoir lu les données, puis prendre des mesures ultérieures (relisez les informations de modification, ou

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


Résumé :
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!

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