Atomic(原子性)

优质
小牛编辑
136浏览
2023-12-01

基于 Swoole 提供的 Swoole\Atomic,直接在配置文件中设置,就可以在worker进程中使用,数据互通。

使用时无需加锁!

配置方式

在项目配置文件中加入以下节

'atomics'    =>    [
    // 定义名为name1的,初始值为0
    'name1',
    // 定义名为name2的,初始值为10
    'name2'    =>    10,
],

使用方式

use \Imi\Util\AtomicManager;

// 获取 Swoole\Atomic 对象
$atomic = AtomicManager::getInstance('name1');

// 加1,返回结果
$number = AtomicManager::::add('name1');

// 加10,返回结果
$number = AtomicManager::::add('name1', 10);

// 减1,返回结果
$number = AtomicManager::::sub('name1');

// 减10,返回结果
$number = AtomicManager::::sub('name1', 10);

// 获取当前值
$number = AtomicManager::get('name1');

// 设置当前值为100
AtomicManager::get('name1', 100);

// -----------------------------------------------

// 如果当前数值等于100返回true,并将当前数值设置为1
// 如果当前数值不等于100返回false
$number = AtomicManager::cmpset('name1', 100, 1);

/**
 * 当原子计数的值为0时程序进入等待状态。另外一个进程调用wakeup可以再次唤醒程序。底层基于Linux Futex实现,使用此特性,可以仅用4字节内存实现一个等待、通知、锁的功能。
 * 超时返回false,错误码为EAGAIN,可使用swoole_errno函数获取
 * 成功返回true,表示有其他进程通过wakeup成功唤醒了当前的锁
 * 使用wait/wakeup特性时,原子计数的值只能为0或1,否则会导致无法正常使用
 * 当然原子计数的值为1时,表示不需要进入等待状态,资源当前就是可用。wait函数会立即返回true
 * @param string $name 原子计数对象名称
 * @param float $timeout 指定超时时间,默认为-1,表示永不超时,会持续等待直到有其他进程唤醒
 * @return bool
 */
$result = AtomicManager::wait('name1');
// 超时时间100毫秒
$result = AtomicManager::wait('name1', 0.1);

/**
 * 唤醒处于wait状态的其他进程。
 * 当前原子计数如果为0时,表示没有进程正在wait,wakeup会立即返回true
 * 当前原子计数如果为1时,表示当前有进程正在wait,wakeup会唤醒等待的进程,并返回true
 * 如果同时有多个进程处于wait状态,$n参数可以控制唤醒的进程数量
 * 被唤醒的进程返回后,会将原子计数设置为0,这时可以再次调用wakeup唤醒其他正在wait的进程
 * @param string $name 原子计数对象名称
 * @param integer $n
 * @return void
 */
AtomicManager::wakeup('name1'); // 第二个参数我也不知道干嘛的,swoole文档没写