Java: Comment faire verrouillage revérifié avec un élément de tableau?
-
29-09-2019 - |
Question
est ce que mon code ressemble actuellement:
private boolean[] isInitialized = new boolean[COUNT];
private void ensureInitialized(int i) {
if (! isInitialized[i]) {
initialize(i);
isInitialized[i] = true;
}
}
Maintenant, je veux avoir thread-safe. Je sais que verrouillage revérifié en Java est « Teh 3vilness !! 1 », mais depuis ensureInitialized
peut être appelé très souvent, je ne veux pas qu'il soit synchronisé. Donc, je pense à faire ceci:
private boolean[] isInitialized = new boolean[COUNT];
private void ensureInitialized(int i) {
if (! isInitialized[i]) {
synchronized (this) {
if (! isInitialized[i]) {
initialize(i);
isInitialized[i] = true;
}
}
}
}
Maintenant que dois-je faire pour ce fil réellement sans danger?
Certains sous-questions:
- Faire
isInitialized
volatile n'est pas nécessaire, puisque la variable ne change pas, non? - Les éléments du tableau sont modifiés, comment puis-je les volatiles?
- Y at-il des moyens généralement mieux de le faire?
(également remarquer que ceci est une méthode d'instance, initialiseur si statique ne fonctionnera)
La solution
S'il vous plaît noter que la mise en œuvre java de double contrôle est appelé « motif brisé », car il a été prouvé que fail (par exemple, voir http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html ). Pour contourner simplement utiliser l'opération atomique. Suivez est exemple comment construire fil singleton sécurité:
static AtomicReferenceArray<Boolean> instance =
new AtomicReferenceArray<Boolean>(COUNT);
private void ensure(int i)
{
if(!instance.get(i) )
{
synchronized(this){
if( !instance.get(i) ){
initialize(i);
instance.set(i, true);
}
}
}
Autres conseils
Vous pouvez également envisager d'utiliser Suppliers.memoize(Supplier<T> delegate)
bibliothèque de goyave .