„Die Zibetkatze tauscht sich gegen den Prinzen aus.“ Die damals geliebten Konkubinen Konkubine Liu und Konkubine Li sind alle schwanger. Es ist offensichtlich, dass jeder, der einen Sohn zur Welt bringt, der Hauptpalast werden kann. Konkubine Liu war schon lange eifersüchtig und befürchtete, dass Konkubine Li einen Sohn zur Welt bringen und zur Königin ernannt werden würde, also schmiedete sie einen Plan mit Guo Huai, dem Palastverwalter Dutang, und in Zusammenarbeit mit der Hebamme Youshi, Konkubine Li starb während der Geburt im Koma. Unerwarteterweise wurde einer Zibetkatze das Fell abgezogen, es war blutig und glänzend und nahm den neugeborenen Prinzen mit. Konkubine Liu befahl der Palastmagd Kou Zhu, den Prinzen zu erwürgen, und übergab den Prinzen heimlich dem Eunuchen. Chen Lin steckte den Prinzen in einen Koffer und schickte ihn zu den Acht weisen Königen um ihn zu erziehen. Außerdem sah Zhenzong die gehäutete Zibetkatze und dachte, dass Konkubine Li ein Monster zur Welt gebracht hatte, also degradierte er sie in den kalten Palast. Bald hatte Konkubine Liu Wehen und gebar einen Sohn, der zum Prinzen ernannt wurde und ebenfalls zur Königin ernannt wurde. Sechs Jahre später starb Königin Lius Sohn unerwartet an einer Krankheit. Zhenzong hatte keine Erben mehr, also adoptierte er den Sohn seines älteren Bruders Baxian Wang (eigentlich der Prinz, der in diesem Jahr ersetzt worden war) als seinen Adoptivsohn und ernannte ihn zum Kronprinzen.
In einem Multithread-Szenario
Problem gibt es hier eine einfache Wissenschaft zum ABA-Problem. Beispielsweise gibt es zwei Threads, die CAS-Operationen mit demselben Wert ausführen (Anfangswert). A) gleichzeitig. Die drei Threads lauten wie folgt:Thread 1 erhält die CPU-Zeitscheibe Zuerst erhält Thread 2 aus anderen Gründen zuerst die CPU-Zeitscheibe. Der Grund ist blockiert. Der Wert von Thread 1 wird mit dem erwarteten Wert von A verglichen. Es wird festgestellt, dass er gleich ist, und dann wird der Wert auf B aktualisiert Zu diesem Zeitpunkt erscheint Thread 3, der erwartete Wert ist B, der zu aktualisierende Wert ist A und der Wert von Thread 3 ist derselbe wie der erwartete Wert. Vergleichen Sie den Wert B und aktualisieren Sie ihn, wenn festgestellt wird, dass er gleich ist der Wert auf A. Zu diesem Zeitpunkt erholt sich Thread 2 von der Blockierung und erhält die CPU-Zeitscheibe. Zu diesem Zeitpunkt wird der Wert von Thread 2 mit dem erwarteten Wert A verglichen. Wenn festgestellt wird, dass er gleich ist, wird der Wert aktualisiert zu B. Obwohl Thread 2 den Vorgang ebenfalls abgeschlossen hat, weiß Thread 2 nicht, dass der Wert den Änderungsprozess von A->B->A durchlaufen hat.
Xiao Ming hat 50 Yuan vom Geldautomaten abgehoben, es gab zwei Threads und der Kontostand wurde gleichzeitig von 100 auf 50 geändert Zeit:
An dieser Stelle können Sie sehen, dass der tatsächliche Saldo sein sollte: 100(100-50+50)
,但是实际上变为了50(100-50+50-50)
Dies ist das ABA-Problem, das zu falschen Einreichungsergebnissen führt.
Um das ABA-Problem zu lösen, können Sie eine Versionsnummer hinzufügen. Jedes Mal, wenn der Wert des Speicherorts V geändert wird, wird die Versionsnummer um 1 erhöht
AtomicStampedReference behält den Objektwert und die Versionsnummer intern bei den Anfangswert übergeben und ursprüngliche Version Nr.;
Wenn AtomicStampedReference den Objektwert festlegt, müssen sowohl der Objektwert als auch der Statusstempel den erwarteten Wert erfüllen, damit der Schreibvorgang erfolgreich ist.
private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100,1); public static void main(String[] args) { //第一个线程 new Thread(() -> { System.out.println("t1拿到的初始版本号:" + atomicStampedReference.getStamp()); //睡眠1秒,是为了让t2线程也拿到同样的初始版本号 try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } atomicStampedReference.compareAndSet(100, 101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1); atomicStampedReference.compareAndSet(101, 100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1); },"t1").start(); // 第二个线程 new Thread(() -> { int stamp = atomicStampedReference.getStamp(); System.out.println("t2拿到的初始版本号:" + stamp); //睡眠3秒,是为了让t1线程完成ABA操作 try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("最新版本号:" + atomicStampedReference.getStamp()); System.out.println(atomicStampedReference.compareAndSet(100, 2019,stamp,atomicStampedReference.getStamp() + 1) + "\t当前值:" + atomicStampedReference.getReference()); },"t2").start(); }
1. Threads t1 und t2 erhalten die gleiche anfängliche Versionsnummer
3. Thread t1 schließt den ABA-Vorgang ab und die Versionsnummer wird auf 3
4 erhöht . Thread t2 Der CAS-Vorgang ist zu 3 geworden, was nicht mit der Versionsnummer 1 übereinstimmt, die zuvor von Thread t2 erhalten wurde. Das Ergebnis der Ausführung:
Lösen Sie das ABA-Problem durch AtomicMarkableReference
t1拿到的初始版本号:1 t2拿到的初始版本号:1 最新版本号:3 false 当前值:100
AtomicStampedReference
可以给引用加上版本号,追踪引用的整个变化过程,如:A -> B -> C -> D -> A,通过AtomicStampedReference,我们可以知道,引用变量中途被更改了3次。但是,有时候,我们并不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了AtomicMarkableReference
t1版本号是否被更改:false t2版本号是否被更改:false 是否更改过:true false 当前值:100多说几句
以上是本期关于CAS领域的一个经典ABA问题的解析,不知道你在实际的工作中有没有遇到过,但是在面试中这块是并发知识考查的重点。如果你还没接触过此类的问题,我的建议是你自己将上面的代码运行一下,结合理论去理解一下ABA问题所带来的问题以及如何解决他,这对你日后的开发工作也是有莫大的帮助的!
Das obige ist der detaillierte Inhalt vonDer Interviewer fragt Sie: Wissen Sie, was ein ABA-Problem ist?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!