cas
(Требуется версия Workerman>=3.3.0)
bool \GlobalData\Client::cas(string $key, mixed $old_value, mixed $new_value)
Атомарная замена, заменяет $old_value
на $new_value
.
Значение может быть записано только в том случае, если после последнего считывания текущим клиентом значение по ключу не было изменено другими клиентами.
Параметры
$key
Ключ. (например, если $global->abc
, то abc
- это ключ)
$old_value
Старое значение
$new_value
Новое значение
Возвращаемое значение
Возвращает true в случае успешной замены, в противном случае возвращает false.
Пояснение:
При одновременной работе нескольких процессов с одной общей переменной иногда необходимо учитывать проблемы параллелизма.
Например, процессы A и B одновременно добавляют элемент в список пользователей.
При этом в текущий момент список пользователей для процессов A и B имеет значение $global->user_list = array(1,2,3)
.
Процесс A работает с переменной $global->user_list
, добавляя пользователя 4.
Процесс B работает с переменной $global->user_list
, добавляя пользователя 5.
Процесс A устанавливает переменную $global->user_list = array(1,2,3,4)
успешно.
Процесс B устанавливает переменную $global->user_list = array(1,2,3,5)
успешно.
При этом значение, установленное процессом B, перезаписывает значение, установленное процессом A, что приводит к потере данных.
В данном случае возникают проблемы параллелизма из-за того, что чтение и установка не являются атомарными операциями.
Для решения этой проблемы параллелизма можно использовать атомарный метод замены cas.
Метод cas перед изменением значения проверяет, не изменялось ли его значение другими процессами с помощью $old_value
и возвращает false, если были изменения. В противном случае возвращает true.
Обратитесь к примеру ниже.
Примечание:
Некоторые общие данные могут быть перезаписаны параллельно без проблем, например, текущая максимальная ставка в системе аукционов, текущий запас определенного товара и т. д.
Пример
$global = new GlobalData\Client('127.0.0.1:2207');
// Инициализация списка
$global->user_list = array(1,2,3);
// Атомарно добавляем значение в 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);