cas

(Erfordert Workerman Version >=3.3.0)

bool \GlobalData\Client::cas(string $key, mixed $old_value, mixed $new_value)

Atomarer Austausch, der $new_value durch $old_value ersetzt.
Nur wenn der Wert, der dem key zugeordnet ist, seit dem letzten Abruf des aktuellen Clients nicht von einem anderen Client geändert wurde, kann der Wert geschrieben werden.

Parameter

$key

Schlüsselwert. (Zum Beispiel $global->abc, abc ist der Schlüsselwert)

$old_value

Alte Daten

$new_value

Neue Daten

Rückgabewert

Gibt true zurück, wenn der Austausch erfolgreich war, andernfalls false.

Hinweis:

Bei gleichzeitigen Operationen mehrerer Prozesse auf dieselbe Shared-Variable müssen oft Konkurrenzen berücksichtigt werden.

Beispielsweise fügen die Prozesse A und B gleichzeitig ein Mitglied zur Benutzerliste hinzu.
Die aktuelle Benutzerliste von Prozess A und B ist $global->user_list = array(1,2,3).
Prozess A bearbeitet die Variable $global->user_list und fügt ein Benutzer 4 hinzu.
Prozess B bearbeitet ebenfalls die Variable $global->user_list und fügt ein Benutzer 5 hinzu.
Prozess A setzt die Variable $global->user_list = array(1,2,3,4) erfolgreich.
Prozess B setzt die Variable $global->user_list = array(1,2,3,5) erfolgreich.
In diesem Moment überschreibt die von Prozess B gesetzte Variable die von Prozess A gesetzte Variable, was zu Datenverlust führt.

Die obigen Probleme entstehen, weil das Lesen und Setzen keine atomare Operation ist, was zu Konkurrenzproblemen führt.
Um solche Konkurrenzprobleme zu lösen, kann die cas-atomare Austausch-Schnittstelle verwendet werden.
Die cas-Schnittstelle überprüft vor der Änderung eines Wertes, ob dieser Wert von anderen Prozessen geändert wurde,
basierend auf $old_value.
Wenn er geändert wurde, wird nicht ersetzt und false zurückgegeben. Andernfalls wird true zurückgegeben.
Siehe das folgende Beispiel.

Hinweis:
Es ist unproblematisch, wenn einige Shared-Daten gleichzeitig überschrieben werden, wie z.B. beim Auktionssystem der aktuelle Höchstgebot eines Auktionsobjekts oder der aktuelle Lagerbestand eines Produkts.

Beispiel

$global = new GlobalData\Client('127.0.0.1:2207');

// Benutzerliste initialisieren
$global->user_list = array(1,2,3);

// Atomar einen Wert zur user_list hinzufügen
do
{
    $old_value = $new_value = $global->user_list;
    $new_value[] = 4;
}
while(!$global->cas('user_list', $old_value, $new_value));

var_export($global->user_list);