recherche

Maison  >  Questions et réponses  >  le corps du texte

java - AQS中源码疑问

AbstractQueuedSynchronizer类中维护了一个用volatile修饰的state状态,而这个状态有如下的两种修改方法:

protected final void setState(int newState) {
    state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

那么,我的疑问来了,不是说volatile修饰的变量在多线程的单操作中,能够保证其写后读的可见性,即能保证线程安全,为什么还提供了CAS操作能保证线程安全呢?还是我的理解有问题呢?谢谢各位大牛了!

巴扎黑巴扎黑2802 Il y a quelques jours629

répondre à tous(3)je répondrai

  • 高洛峰

    高洛峰2017-04-18 10:50:23

    Il n'y a pas de conflit. setState est juste une opération d'écriture et ne se soucie pas de l'état d'origine. Par exemple, l'état était à l'origine 0. Le thread 1 et le thread 2 lisent respectivement la valeur 0. puis le thread 2 prévoit de le définir sur 2, ce qui peut réussir. Bien que l'état soit déjà 1 et que le thread 2 le sache également, cela n'a pas d'importance. Le thread 2 le définit simplement sur 2. La méthode suivante ne fonctionnera pas.

    répondre
    0
  • ringa_lee

    ringa_lee2017-04-18 10:50:23

    Oui, il y a un problème avec votre compréhension.

    Cela ne signifie pas que les variables volatiles modifiées peuvent garantir la visibilité de la lecture après écriture dans une opération unique multithread, c'est-à-dire que la sécurité des threads peut être garantie

    Être capable de garantir la visibilité ne signifie pas que la sécurité des fils peut être garantie. La visibilité et la sécurité des threads ne sont pas le même concept.

    l'opération cas peut être divisée en plusieurs petites opérations

    1. Comparez les valeurs actuelles des variables attendues et d'état Si elles sont identiques, passez à l'étape 2. Si elles sont différentes, la méthode se termine.

    2. Attribuer une valeur à la mise à jour de l'état

    Si ces deux opérations sont appelées simultanément par plusieurs threads, il y aura des problèmes de sécurité des threads.
    La méthode cas utilise ici l'instruction cas du CPU, qui est une opération atomique. Les problèmes de concurrence peuvent être évités.

    répondre
    0
  • 天蓬老师

    天蓬老师2017-04-18 10:50:23

    En bref :

    1. Si vous ne vous fiez pas à la valeur d'origine, vous pouvez utiliser set

    2. Si vous vous fiez à la valeur d'origine, vous pouvez utiliser cas pour la définir. C’est en soi un verrou optimiste.

    répondre
    0
  • Annulerrépondre