php多进程并发,php多进程模拟并发事务
用实例代码给大家介绍关于php多进程模拟并发事务产生的一些问题,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧
数据表
drop table if exists `test`;
create table if not exists `test` (
id int not null auto_increment ,
count int default 0 ,
primary key `id` (`id`)
) engine=innodb character set utf8mb4 collate = utf8mb4_bin comment '测试表';
insert into test (`count`) values (100);
// 进程数量
$pro_count = 100;
$pids = [];
for ($i = 0; $i < $pro_count; ++$i)
{
$pid = pcntl_fork();
if ($pid < 0) {
// 主进程
throw new Exception('创建子进程失败: ' . $i);
} else if ($pid > 0) {
// 主进程
$pids[] = $pid;
} else {
// 子进程
try {
$pdo = new PDO(...);
$pdo->beginTransaction();
$stmt = $pdo->query('select `count` from test');
$count = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
$count = intval($count);
if ($count > 0) {
$count--;
$pdo->query('update test set `count` = ' . $count . ' where id = 2');
}
$pdo->commit();
} catch(Exception $e) {
$pdo->rollBack();
throw $e;
}
// 退出子进程
exit;
}
}
期望的结果
期望 count 字段减少的量超过 100,变成负数!也就是多减!
实际结果
并发 200 的情况下,运行多次后的结果分别如下:
1. count = 65
2. count = 75
3. count = 55
4. count = 84
...
与期望结果相差甚远!为什么会出现这样的现象呢?
解释
首先清楚下目前的程序运行环境,并发场景。何为并发,几乎同时执行,称之为并发。具体解释如下:
进程 过程 获取 更新
1-40 同时创建并运行 100 99
41-80 同时创建并运行 99 98
81 - 100 同时创建并运行 98 97
对上述第一行做解释,第 1-40 个子进程的创建几乎同时,运行也几乎同时:
进程 1 获取 count = 100,更新 99
进程 2 获取 count = 100,更新 99
...
进程 40 获取 count = 100,更新 99
所以,实际上这些进程都做了一致的操作,并没有按照预期的那样:进程1 获取 count=100,更新 99;进程 2 获取进程1更新后的结果 count=99,更新98;...;进程 99 获取进程 98更新后的结果count=1,更新0
,产生的现象就是少减了!!
结论
采用上述做法实现的程序,库存总是 >= 0。
疑问
那要模拟超库存的场景该如何设计程序呢?
仍然采用上述代码,将以下代码:
if ($count > 0) {
$count--;
$pdo->query('update test set `count` = ' . $count . ' where id = 2');
}
修改成下面这样:
if ($count > 0) {
$pdo->query('update test set `count` = `count` - 1 where id = 2');
}
结果就会出现超库存!!
库存 100,并发 200,最终库存减少为 -63。为什么会出现这样的情况呢?以下描述了程序运行的具体过程
进程 1 获取库存 100,更新 99
进程 2 获取库存 100,更新 98(99 - 1)
进程 3 获取库存 100,更新 97(98 - 1)
....
进程 168 获取库存 1 ,更新 0(1-1)
进程 169 获取库存 1 ,更新 -1(0 - 1)
进程 170 获取库存 1 ,更新 -2(-1 - 1)
....
进程 200 获取库存 1,更新 -63(-62 - 1)
现在看来很懵逼,实际就是下面这条语句导致的:
$pdo->query('update test set `count` = `count` - 1 where id = 2');
这边详细阐述 进程 1,简称 a;进程 2,简称 b 他们具体的执行顺序:
1. a 查询到库存 100
2. b 查询到库存 100
3. a 更新库存为 99(100 - 1),这个应该秒懂
4. b 更新库存为 98(99 - 1)
- b 在执行更新操作的时候拿到的是 a 更新后的库存!
- 为什么会这样?因为更新语句是 `update test set count = count - 1 where id = 2`
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要戳这里PHP进阶架构师>>>实战视频、大厂面试文档免费获取
php多进程并发,php多进程模拟并发事务相关推荐
- php 模拟并发请求_PHP模拟并发请求
原理:使用curl_init()创建多个请求实例,再使用curl_multi_init()批量执行创建的多个请求实例. 文件1:curl.php<?php $threads=500;//并发请求 ...
- python模拟app抢票_python并发编程多进程 模拟抢票实现过程
抢票是并发执行 多个进程可以访问同一个文件 多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务 db.txt {"count": 1} 并发运行,效率高 ...
- Python 3 并发编程多进程之进程同步(锁)
Python 3 并发编程多进程之进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,竞争带来的结果就是错乱,如何控制,就是加锁处理. 1. ...
- Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型
一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...
- python 并发编程 多进程 目录
python multiprocessing模块 介绍 python 开启进程两种方法 python 并发编程 查看进程的id pid与父进程id ppid python 并发编程 多进程 Proce ...
- 对PHP并发、多进程、多线程、异步处理、分布式系统的一些了解
目录 并发 基本概念 PHP并发模型 多进程 基本概念 进程 多进程 并发多任务 任务调度 PHP实现多进程 PCNTL PHP-FPM Swoole 多线程 基本概念 线程 多线程 PHP实现多线程 ...
- 第五十一篇 并发编程——多进程
目录 第五十一篇 并发编程--多进程 一.什么是进程 经典举例说明进程,以及切换 二.进程与程序 三.线程 进程和线程的关系 四.进程PID与PPID 1.PID 2.PPID 五.并发与并行,阻塞与 ...
- 128-网络编程:TCP通信的并发(多进程实现并发服务器)
3.TCP通信的并发(多进程实现并发服务器) 3.1 多进程实现并发服务器 要实现TCP通信服务器处理并发任务,使用多线程或者多进程来解决. 思路:1. 一个父进程,多个子进程2. 父进程负责等待并接 ...
- 并发服务器模型——多进程服务器
多进程服务器 1. 多进程服务器 from socket import * from multiprocessing import * from time import sleep# 处理客户端的请求 ...
最新文章
- Java 9.while语句
- 【数据竞赛】ICCV 2021 竞赛汇总
- 调焦后焦实现不同距离成像_“物镜校正环调节”对显微成像的影响
- checking for mysql_commit in -lmy_mysql2安装异常
- java--xml文件读取(SAX)
- h.264 视频解码的一点小经验
- 《Netty权威指南》第2章 NIO入门
- mac新手入门:如何在Mac上禁用通知预览?
- matlab高斯滤波跟中值滤波区别,基于MATLAB图像处理的中值滤波、均值滤波以及高斯滤波的实现与对比...
- PS4 5.05安装Linux系统,PS4主机刷机教程以及游戏安装教程,到5.05 4.55 4.05等系统
- 通过计算机英语怎么说,通过英文怎么说
- 大禹电子:超声波小型水声通信机可用于水下实时定位系统
- html借助JS简单实现图片闪烁功能
- RN 组件 Animated
- iOS开发:GitHub上传代码错误提示fatal: Authentication failed for 'https://gitee.com/XXX/XXX.git/‘的解决方法
- wordpress 数据库_如何在WordPress中创建视频库(逐步)
- 安装文本编辑器 Geany
- 记录h5文件数据转为npy和csv格式类型的方法
- 关于串口通信SBUF寄存器随笔:
- php 分数大于80 小于90优,“ 90 分改成 80 分”学生期末成绩须“正态分布”?不必搞一刀切...
热门文章
- java - 计算距离和反弹
- python include的功能_在Python的Config中增加Include功能
- 机器人穿法_(图解)机器人系统组成介绍
- python 网络编程 异步io_异步IO实现 小例(程序+驱动程序)
- C++类模板5分钟入门
- Python中map()函数用法
- springboot jpa 创建数据库以及rabbitMQ分模块扫描问题
- Visual Paradigm中文乱码
- C#缓存absoluteExpiration、slidingExpiration两个参数的疑惑
- Linux 权限、磁盘操作命令-Linux基础环境命令学习笔记