用实例代码给大家介绍关于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多进程模拟并发事务相关推荐

  1. php 模拟并发请求_PHP模拟并发请求

    原理:使用curl_init()创建多个请求实例,再使用curl_multi_init()批量执行创建的多个请求实例. 文件1:curl.php<?php $threads=500;//并发请求 ...

  2. python模拟app抢票_python并发编程多进程 模拟抢票实现过程

    抢票是并发执行 多个进程可以访问同一个文件 多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务 db.txt {"count": 1} 并发运行,效率高 ...

  3. Python 3 并发编程多进程之进程同步(锁)

    Python 3 并发编程多进程之进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,竞争带来的结果就是错乱,如何控制,就是加锁处理. 1. ...

  4. Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型

    一.背景知识 进程即正在执行的一个过程.进程是对正在运行的程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其他所有内容都 ...

  5. python 并发编程 多进程 目录

    python multiprocessing模块 介绍 python 开启进程两种方法 python 并发编程 查看进程的id pid与父进程id ppid python 并发编程 多进程 Proce ...

  6. 对PHP并发、多进程、多线程、异步处理、分布式系统的一些了解

    目录 并发 基本概念 PHP并发模型 多进程 基本概念 进程 多进程 并发多任务 任务调度 PHP实现多进程 PCNTL PHP-FPM Swoole 多线程 基本概念 线程 多线程 PHP实现多线程 ...

  7. 第五十一篇 并发编程——多进程

    目录 第五十一篇 并发编程--多进程 一.什么是进程 经典举例说明进程,以及切换 二.进程与程序 三.线程 进程和线程的关系 四.进程PID与PPID 1.PID 2.PPID 五.并发与并行,阻塞与 ...

  8. 128-网络编程:TCP通信的并发(多进程实现并发服务器)

    3.TCP通信的并发(多进程实现并发服务器) 3.1 多进程实现并发服务器 要实现TCP通信服务器处理并发任务,使用多线程或者多进程来解决. 思路:1. 一个父进程,多个子进程2. 父进程负责等待并接 ...

  9. 并发服务器模型——多进程服务器

    多进程服务器 1. 多进程服务器 from socket import * from multiprocessing import * from time import sleep# 处理客户端的请求 ...

最新文章

  1. Java 9.while语句
  2. 【数据竞赛】ICCV 2021 竞赛汇总
  3. 调焦后焦实现不同距离成像_“物镜校正环调节”对显微成像的影响
  4. checking for mysql_commit in -lmy_mysql2安装异常
  5. java--xml文件读取(SAX)
  6. h.264 视频解码的一点小经验
  7. 《Netty权威指南》第2章 NIO入门
  8. mac新手入门:如何在Mac上禁用通知预览?
  9. matlab高斯滤波跟中值滤波区别,基于MATLAB图像处理的中值滤波、均值滤波以及高斯滤波的实现与对比...
  10. PS4 5.05安装Linux系统,PS4主机刷机教程以及游戏安装教程,到5.05 4.55 4.05等系统
  11. 通过计算机英语怎么说,通过英文怎么说
  12. 大禹电子:超声波小型水声通信机可用于水下实时定位系统
  13. html借助JS简单实现图片闪烁功能
  14. RN 组件 Animated
  15. iOS开发:GitHub上传代码错误提示fatal: Authentication failed for 'https://gitee.com/XXX/XXX.git/‘的解决方法
  16. wordpress 数据库_如何在WordPress中创建视频库(逐步)
  17. 安装文本编辑器 Geany
  18. 记录h5文件数据转为npy和csv格式类型的方法
  19. 关于串口通信SBUF寄存器随笔:
  20. php 分数大于80 小于90优,“ 90 分改成 80 分”学生期末成绩须“正态分布”?不必搞一刀切...

热门文章

  1. java - 计算距离和反弹
  2. python include的功能_在Python的Config中增加Include功能
  3. 机器人穿法_(图解)机器人系统组成介绍
  4. python 网络编程 异步io_异步IO实现 小例(程序+驱动程序)
  5. C++类模板5分钟入门
  6. Python中map()函数用法
  7. springboot jpa 创建数据库以及rabbitMQ分模块扫描问题
  8. Visual Paradigm中文乱码
  9. C#缓存absoluteExpiration、slidingExpiration两个参数的疑惑
  10. Linux 权限、磁盘操作命令-Linux基础环境命令学习笔记