cas

(Requires Workerman version >= 3.3.0)

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

Substituição atômica, substitua $old_value por $new_value.
Apenas se o valor correspondente a essa chave não foi modificado por outro cliente desde a última vez que foi acessado pelo cliente atual, o valor pode ser escrito.

Parâmetros

$key

Chave. (por exemplo, se for $global->abc, abc é a chave)

$old_value

Dado antigo

$new_value

Novo dado

Valor de Retorno

Retorna true se a substituição for bem-sucedida, caso contrário retorna false.

Observação:

Quando vários processos operam simultaneamente em uma variável compartilhada, às vezes é necessário considerar problemas de concorrência.

Por exemplo, os processos A e B estão adicionando um membro à lista de usuários ao mesmo tempo.
Os processos A e B têm a variável de lista de usuários atual como $global->user_list = array(1,2,3).
O processo A está manipulando a variável $global->user_list, adicionando um usuário 4.
O processo B está manipulando a variável $global->user_list, adicionando um usuário 5.
O processo A configura a variável como $global->user_list = array(1,2,3,4) com sucesso.
O processo B configura a variável como $global->user_list = array(1,2,3,5) com sucesso.
Neste momento, a variável configurada pelo processo B substitui a variável configurada pelo processo A, resultando na perda de dados.

Isso ocorre devido a leitura e escrita não serem uma operação atômica, resultando em problemas de concorrência.
Para resolver esse tipo de problema de concorrência, pode-se usar a interface de substituição atômica (cas).
Antes de alterar um valor, a interface cas verifica se o valor foi alterado por outro processo com base em $old_value. Se foi alterado, a substituição não é realizada e retorna false. Caso contrário, retorna true.
Veja o exemplo abaixo.

Observação:
Alguns dados compartilhados sendo substituídos por concorrência não são um problema, como por exemplo, o maior lance atual em um sistema de leilão, ou o estoque atual de um determinado produto.

Exemplo

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

// Inicializar a lista
$global->user_list = array(1,2,3);

// Adiciona um valor atômico à user_list
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);