进程间共享变量

希望可以在进程间共享变量,为共享数据提供快速访问。
使用APCu扩展的数据存储功能
// 确保APCu扩展已安装并启用
if (!function_exists('apcu_fetch')) {
die('APCu extension is not available.');
}

// 初始化变量(这些值通常来自其他数据源,如数据库或用户输入)
$births = 100; // 假设这个月有100个新生儿
$immigrants = 50; // 假设这个月有50个移民入境
$deaths = 80; // 假设这个月有80人死亡
$emigrants = 30; // 假设这个月有30人移民出境

// 尝试从APCu缓存中获取人口值
$population = apcu_fetch('population');

// 如果缓存中不存在人口值,则进行初始化(这里我们假设初始人口为1000)
if ($population === false) {
$population = 1000;
}

// 处理数据:计算新的人口总数
$population += ($births + $immigrants - $deaths - $emigrants);

// 将新的人口总数存回APCu缓存中
apcu_store('population', $population, APCU_F_OVERWRITE); // APCU_F_OVERWRITE表示如果键已存在,则覆盖它

// 输出新的人口总数(仅用于演示)
echo "The new population is: " . $population;


也可以使用PHP附带的两个共享内存扩展:shmop或SystemV共享内存

shmop共享内存:
// 初始化变量(这些值通常来自其他数据源,如数据库或用户输入)
$births = 100; // 假设这个月有100个新生儿
$immigrants = 50; // 假设这个月有50个移民入境
$deaths = 80; // 假设这个月有80人死亡
$emigrants = 30; // 假设这个月有30人移民出境

// 创建键
$shmop_key = ftok(FILE, 'p');

// 创建16384字节共享内存块,并初始化为0(如果它不存在的话)
$shmop_id = shmop_open($shmop_key, "c", 0600, 16384);
if ($shmop_id === false) {
die("Unable to create/open the shared memory segment\n");
}

// 尝试读取当前的人口数,如果不存在则默认为0
$existing_data = shmop_read($shmop_id, 0, 16384); // 读取整个块
$population = (int)trim($existing_data); // 尝试将内容转换为整数,并去除任何前导/尾随空白
if ($population === 0 && $existing_data !== '') {
// 如果转换后的结果为0,但原始数据不为空,则可能是一个错误;这里我们简单地将其视为0
// 在实际应用中,您可能需要更复杂的错误处理逻辑
$population = 0;
} elseif ($existing_data === '') {
// 如果共享内存是空的(即第一次使用),则初始化为0
$population = 0;
}

// 处理数据
$population += ($births + $immigrants - $deaths - $emigrants);

// 将值存回到共享内存段,注意转换为字符串并填充到所需长度(如果需要)
$population_str = str_pad((string)$population, 16384, "\0"); // 使用空字符填充到16384字节
$shmop_bytes_written = shmop_write($shmop_id, $population_str, 0);

// 检查写入是否成功(这里我们检查写入的字节数是否与我们期望的填充后的字符串长度相匹配)
if ($shmop_bytes_written !== strlen($population_str)) {
echo "Can't write all data to shared memory\n";
}

// 关闭句柄
shmop_close($shmop_id);


SystemV共享内存:

// 初始化变量(这些值通常来自其他数据源,如数据库或用户输入)
$births = 100; // 假设这个月有100个新生儿
$immigrants = 50; // 假设这个月有50个移民入境
$deaths = 80; // 假设这个月有80人死亡
$emigrants = 30; // 假设这个月有30人移民出境

// 信号量和共享内存段的标识符(这些ID应该是唯一的,并且需要确保不会与其他进程冲突)
$semaphore_id = ftok(FILE, 'a'); // 使用ftok生成唯一的信号量ID(注意:ftok在Windows上不可用)
// 如果在Windows上运行,需要找到其他方法来生成唯一的ID
$segment_id = ftok(FILE, 'b'); // 使用ftok生成唯一的共享内存段ID

// 尝试获取与共享内存段关联的信号量的句柄
$sem = sem_get($semaphore_id, 1, 0600 | IPC_CREAT); // 添加IPC_CREAT以在信号量不存在时创建它
if ($sem === false) {
die("Can't create or get semaphore");
}

// 确保对信号量的排他访问
if (!sem_acquire($sem)) {
die("Can't acquire semaphore");
}

// 尝试获取共享内存段的句柄
$shm = shm_attach($segment_id, 16384, 0600 | SHM_CREAT | SHM_EXCL); // SHM_CREAT在段不存在时创建它,SHM_EXCL确保段是新创建的(这里可能不需要SHM_EXCL)
if ($shm === false) {
// 如果shm_attach失败(可能是因为段已存在),尝试不带SHM_EXCL标志重新连接
$shm = shm_attach($segment_id, 16384, 0600 | SHM_CREAT);
if ($shm === false) {
die("Can't attach to shared memory segment");
}
}

// 在共享内存段中存储值的整数ID
$var_id = 3476;

// 从共享内存段获取一个值
if (shm_has_var($shm, $var_id)) {
$population = shm_get_var($shm, $var_id);
} else {
// 如果变量还未初始化,则初始化为0
$population = 0;
// 将初始值放入共享内存段(这一步是可选的,因为后续操作会覆盖这个值,但出于完整性考虑还是加上)
shm_put_var($shm, $var_id, $population);
}

// 处理这个值(更新人口数量)
$population += ($births + $immigrants - $deaths - $emigrants);

// 将更新后的值存回到共享内存段
shm_put_var($shm, $var_id, $population);

// 释放共享内存段的句柄
shm_detach($shm);

// 释放信号量,以便其他进程获取这个信号量
sem_release($sem);

// 注意:在实际应用中,您可能还需要考虑清理信号量和共享内存段(例如,在脚本结束时删除它们)
// 但是,这通常是在确保没有其他进程正在使用它们之后才进行的操作
// 可以使用sem_remove($sem)和shm_remove($segment_id)函数来删除信号量和共享内存段
// 但请注意,这些操作通常是危险的,因为如果其他进程正在使用这些资源,删除它们可能会导致未定义的行为

posted @   kksllss  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示