CAS ist CompareAndSwap, was Vergleich und Austausch bedeutet. Warum verwendet CAS keine Sperren, gewährleistet aber dennoch eine sichere Datenmanipulation unter gleichzeitigen Bedingungen? Der Name zeigt das Prinzip von CAS tatsächlich sehr intuitiv. Der spezifische Prozess der Datenänderung ist wie folgt: #🎜🎜 #Wenn Sie CAS zum Bearbeiten von Daten verwenden, übergeben Sie den ursprünglichen Wert der Daten und den zu ändernden Wert an die Methode
Vergleichen Sie, ob der aktuelle Zielvariablenwert vorliegt ist derselbe wie der ursprüngliche Wert, der in übergeben wurde
Wenn sie gleich sind, bedeutet dies, dass die Zielvariable nicht von anderen Threads geändert wurde. Ändern Sie einfach die Zielvariable Wert direkt
CAS implementiert sperrenfreie Programmierung
Sperrenfreie Programmierung bezieht sich auf den sicheren Betrieb gemeinsamer Variablen ohne Verwendung von Sperren#🎜 🎜#In Bei der gleichzeitigen Programmierung verwenden wir verschiedene Sperren, um die Sicherheit gemeinsam genutzter Variablen zu gewährleisten. Das heißt, es ist garantiert, dass andere Threads nicht dieselbe gemeinsam genutzte Variable bearbeiten können, wenn ein Thread die Bedienung der gemeinsam genutzten Variablen noch nicht abgeschlossen hat.
Die korrekte Verwendung von Sperren kann die Datensicherheit bei Parallelität gewährleisten. Wenn jedoch der Grad der Parallelität nicht hoch ist und der Wettbewerb nicht hart ist, wird der Erwerb und die Freigabe von Sperren zu unnötiger Leistungsverschwendung. In diesem Fall können Sie die Verwendung von CAS in Betracht ziehen, um die Datensicherheit zu gewährleisten und eine sperrenfreie Programmierung zu erreichen. Der obige CAS-Vorgang weist jedoch immer noch Mängel auf. Angenommen, der Wert der gemeinsam genutzten Variablen, auf die der aktuelle Thread zugreift, ist A. Während Thread 1 auf die gemeinsam genutzte Variable zugreift, bedient Thread 2 die gemeinsam genutzte Variable und weist ihr den Wert B zu. Nachdem Thread 2 seine eigene Logik verarbeitet hat, wird er verwendet weist der gemeinsam genutzten Variablen den Wert A zu. Zu diesem Zeitpunkt vergleicht Thread 1 den Wert A der gemeinsam genutzten Variablen mit dem ursprünglichen Wert A, geht fälschlicherweise davon aus, dass kein anderer Thread die gemeinsam genutzte Variable betreibt, und gibt direkt den Erfolg der Operation zurück. Das ist das ABA-Problem. Obwohl sich die meisten Unternehmen nicht darum kümmern müssen, ob andere Änderungen an gemeinsam genutzten Variablen vorgenommen wurden, kann das korrekte Ergebnis erzielt werden, solange der ursprüngliche Wert mit dem aktuellen Wert übereinstimmt. Es gibt jedoch einige sensible Szenarien, in denen nicht nur die Das Ergebnis der gemeinsam genutzten Variablen ist gleichbedeutend damit, dass sie nicht geändert wird, aber es ist auch nicht akzeptabel, dass gemeinsam genutzte Variablen von anderen Threads im Prozess geändert werden. Glücklicherweise gibt es eine ausgereifte Lösung für das ABA-Problem. Wir fügen der gemeinsam genutzten Variablen eine Versionsnummer hinzu, und der Wert der Versionsnummer erhöht sich automatisch, wenn die gemeinsam genutzte Variable geändert wird. Bei der CAS-Operation vergleichen wir nicht den ursprünglichen Variablenwert, sondern die Versionsnummer der gemeinsam genutzten Variablen. Die für jede Operation mit gemeinsam genutzten Variablen aktualisierte Versionsnummer ist eindeutig, sodass das ABA-Problem vermieden werden kann.
CAS-Anwendung im JDKErstens ist es unsicher, wenn mehrere Threads gleichzeitig mit gewöhnlichen Variablen arbeiten Das Operationsergebnis kann von anderen Threads überschrieben werden. Jetzt verwenden wir zwei Threads, und jeder Thread erhöht den Anfangswert 1. Wenn kein Synchronisationsmechanismus vorhanden ist, ist das Ergebnis der gemeinsam genutzten Variablen wahrscheinlich kleiner als 3 sein. Das heißt, es ist möglich, dass sowohl Thread 1 als auch Thread 2 den Anfangswert 1 gelesen haben, Thread 1 ihn 2 zuweist und der von Thread 2 aus dem Speicher gelesene Wert, in dem er sich befindet, auch die Variable erhöht durch 1 und weist es 2 zu, sodass das Endergebnis 2 ist, was kleiner ist als das erwartete Ergebnis von 3. Die Inkrementierungsoperation ist keine atomare Operation, was zu dem unsicheren Problem der gemeinsam genutzten Variablenoperation führt. Um dieses Problem zu lösen, stellt JDK eine Reihe atomarer Klassen bereit, um entsprechende atomare Operationen bereitzustellen. Das Folgende ist der Quellcode der getAndIncrement-Methode in AtomicInteger. Schauen wir uns den Quellcode an, um zu sehen, wie man mit CAS die threadsichere atomare Addition von Ganzzahlvariablen implementiert.
<code>/**<br> * 原子性的将当前值增加1<br> *<br> * @return 返回自增前的值<br> */<br>public final int getAndIncrement() {<br> return unsafe.getAndAddInt(this, valueOffset, 1);<br>}<br></code>
<code>/**<br> * 原子的将给定值与目标字变量相加并重新赋值给目标变量<br> *<br> * @param o 要更新的变量所在的对象<br> * @param offset 变量字段的内存偏移值<br> * @param delta 要增加的数字值<br> * @return 更改前的原始值<br> * @since 1.8<br> */<br>public final int getAndAddInt(Object o, long offset, int delta) {<br> int v;<br> do {<br> // 获取当前目标目标变量值<br> v = getIntVolatile(o, offset);<br> // 这句代码是关键, 自旋保证相加操作一定成功<br> // 如果不成功继续运行上一句代码, 获取被其他<br> // 线程抢先修改的变量值, 在新值基础上尝试相加<br> // 操作, 保证了相加操作的原子性<br> } while (!compareAndSwapInt(o, offset, v, v + delta));<br> return v;<br>}<br></code>
Angenommen, die Struktur und Daten der Benutzertabelle sind wie folgt. Das Versionsfeld ist der Schlüssel zur Implementierung einer optimistischen Sperre
id
user
coupon_num
# 🎜 🎜#1#🎜 🎜#
0 |
---|
Das obige ist der detaillierte Inhalt vonSo verwenden Sie CAS und Java Optimistic Locking. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!