2010-03-14 7 views
42

(Notez que cette question ne concerne pas CAS, il s'agit de la "Peut échouer faussement" Javadoc).Comment weakCompareAndSet peut-il échouer faussement s'il est implémenté exactement comme compareAndSet?

La seule différence dans la Javadoc entre ces deux méthodes de la classe AtomicInteger est que le weakCompareAndSet contient le commentaire: « peut échouer spuriously ».

Maintenant, à moins que mes yeux sont floués par un sort, les deux méthode ne semblent être en train de faire exactement la même chose:

public final boolean compareAndSet(int expect, int update) { 
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 
} 

/* ... 
* May fail spuriously. 
*/ 
public final boolean weakCompareAndSet(int expect, int update) { 
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 
} 

Alors je me rends compte que « mai » ne signifie pas « doit », mais alors pourquoi ne « t nous commençons à ajouter ceci à notre base de code:

public void doIt() { 
    a(); 
} 

/** 
* May fail spuriously 
*/ 
public void weakDoIt() { 
    a(); 
} 

Je suis vraiment confondu avec celui weakCompareAndSet() qui semble faire la même chose que le compareAndSet() encore que « peut échouer spuriously » tandis que l'autre ne le peut pas.

Apparemment, le "faible" et le "faux échec" sont en quelque sorte liés à la commande "arrive avant" mais je suis encore très confus par ces deux méthodes AtomicInteger (et AtomicLong etc.): appelez exactement les mêmes unsafe.compareAndSwapInt méthode.

Je suis particulièrement confus dans cette AtomicInteger en Java ai été présenté 1.5, après le changement de modèle Java Memory (il est donc évidemment pas quelque chose qui pourrait « fail 1.4 dans spuriously » mais dont le comportement changé « doit pas échouer faussement dans 1.5 ").

+0

Bonne question Wiz –

+0

Bizarre en effet. Il pourrait s'agir d'une vérification de l'avenir de l'API, mais c'est une façon étrange de s'y prendre. Il semble que toutes les classes 'AtomicXYZ' font la même chose dans' compareAndSet' et 'weakCompareAndSet', ce n'est donc pas non plus une question de cohérence entre les implémentations. – skaffman

+0

Voir aussi http://stackoverflow.com/questions/4183202/java-compare-and-swap-semantics-and-performance – assylias

Répondre

19

Il y a une différence entre la mise en œuvre et la spécification ...

Alors que sur une mise en œuvre particulière, il ne peut pas être beaucoup d'intérêt à fournir différentes implémentations, les implémentations futures peut-être sur un matériel différent peut vouloir. Si cette méthode porte son poids dans l'API est discutable.

Les méthodes weak ne possèdent pas non plus de happen-before définie par ordre. Les versions non weak se comportent comme des champs volatile.

+0

@Tom Hawtin - tackline: +1 ... Connaissez-vous une implémentation JVM (Sun ou non-Sun) sur tout matériel où il existe différentes implémentations pour de telles méthodes? – SyntaxT3rr0r

+0

Non, je ne sais même pas s'il y a du matériel grand public qui pourrait faire la différence. Je crois que pour obtenir le faible comportement volatile, il faut le faire pour tout. Bien sûr, l'autre côté des choses est le compilateur, qui pourrait laisser des données dans des registres qui seraient autrement vidés. –

+0

"Les méthodes faibles n'ont pas non plus lieu avant l'ordre défini, les versions non-faibles se comportent comme des champs volatiles." Si oui, quel est le point d'une telle méthode dans java.util.concurrent.atomic; paquet? – Rollerball

1

Juste pour jouer un peu, si votre question était

Comment peut-weakDoIt échouer si elle est fallacieuse mis en œuvre exactement comme doIt?

voici la réponse!

public void doIt() { 
    a(); 
} 

/** 
* May fail spuriously 
*/ 
public void weakDoIt() { 
    a(); 
} 

void a(){ 
    if(Thread.currentThread().getStackTrace()[2].toString().contains("weakDoIt")) 
     System.out.println("I will fail spuriously!"); 
    else System.out.println("I won't fail spuriously!"); 
}