php 的多进程实践
php的多进程处理依赖于pcntl扩展,通过pcntl_fork创建子进程来进行并行处理。
<?php
$pid = pcntl_fork(); if($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('fork error');
} else if ($pid) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
echo "parent \n";
//等待子进程中断,防止子进程成为僵尸进程。
pcntl_wait($status);
} else {
//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
echo "child \n"; exit;
}
<?php
$pid = pcntl_fork(); if($pid == -1) {
die('fork error');
} else if ($pid) {
sleep(3);
echo "parent \n";
pcntl_wait($status);
} else {
echo "child \n"; exit;
}
<?php
$pid = pcntl_fork(); if($pid == -1) {
die('fork error');
} else if ($pid) {
pcntl_wait ($status);
echo "parent \n";
} else {
sleep(3);
echo "child \n"; exit;
}
<?php
define('FORK_NUMS', 3); $pids = array(); for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
pcntl_waitpid($pids[$i], $status);
echo "pernet \n";
} else {
sleep(3);
echo "child id:" . getmypid() . " \n";
exit;
}
}
上述代码,我们创建3个子进程,父进程分别挂起等待子进程结束后,输出parent。
child id:19090
pernet
child id:19091
pernet
child id:19092
pernet
<?php
define('FORK_NUMS', 3); $pids = array(); for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) { } else {
sleep(3);
echo "child id:" . getmypid() . " \n";
exit;
}
} foreach($pids as $k => $v) {
if($v) {
pcntl_waitpid($v, $status);
echo "parent \n";
}
}
输出结果如下:
child id:19118
child id:19119
child id:19120
parent
parent
parent
为什么上述代码跟例4的输出结果不一样?
<?php define('FORK_NUMS', 3); $pids = array(); $fp = fopen('./test.log', 'wb');
$num = 1; for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) { } else {
for($i = 0; $i < 5; ++$i) { flock($fp, LOCK_EX);
fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {$num} \r\n"); flock($fp, LOCK_UN);
echo getmypid(), ": success \r\n";
++$num;
}
exit;
}
} foreach($pids as $k => $v) {
if($v) {
pcntl_waitpid($v, $status);
}
} fclose($fp);
19507 : 2016-03-16 20:40:52 : 1
19507 : 2016-03-16 20:40:52 : 2
19507 : 2016-03-16 20:40:52 : 3
19507 : 2016-03-16 20:40:52 : 4
19507 : 2016-03-16 20:40:52 : 5
19509 : 2016-03-16 20:40:52 : 1
19509 : 2016-03-16 20:40:52 : 2
19509 : 2016-03-16 20:40:52 : 3
19509 : 2016-03-16 20:40:52 : 4
19509 : 2016-03-16 20:40:52 : 5
19508 : 2016-03-16 20:40:52 : 1
19508 : 2016-03-16 20:40:52 : 2
19508 : 2016-03-16 20:40:52 : 3
19508 : 2016-03-16 20:40:52 : 4
19508 : 2016-03-16 20:40:52 : 5
我们可以看到三个子进程的pid,它们分别执行了5次,时间几乎是在同时。但是$num的值并没像我们期望的那样从1-15进行递增。子进程中的变量是各自独立的,互不影响。子进程会自动复制父进程空间里的变量。
<?php define('FORK_NUMS', 3); $pids = array(); $fp = fopen('./test.log', 'wb');
$num = 1;
//共享内存段的key
$shmKey = 123;
//创建共享内存段
$shmId = shmop_open($shmKey, 'c', 0777, 64);
//写入数据到共享内存段
shmop_write($shmId, $num, 0); for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) { //阻塞,等待子进程退出 //注意这里,如果是非阻塞的话,$num的计数会出现问题。
pcntl_waitpid($pids[$i], $status);
} else {
//读取共享内存段中的数据
$num = shmop_read($shmId, 0, 64);
for($i = 0; $i < 5; ++$i) {
fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {$num} \r\n");
echo getmypid(), ": success \r\n";
//递增$num
$num = intval($num) + 1;
} //写入到共享内存段中 shmop_write($shmId, $num, 0);
exit;
}
} //shmop_delete不会实际删除该内存段,它将该内存段标记为删除。
shmop_delete($shmId);
shmop_close($shmId);
fclose($fp);
上述代码的运行结果如下:
19923 : 2016-03-17 00:05:18 : 1
19923 : 2016-03-17 00:05:18 : 2
19923 : 2016-03-17 00:05:18 : 3
19923 : 2016-03-17 00:05:18 : 4
19923 : 2016-03-17 00:05:18 : 5
19924 : 2016-03-17 00:05:18 : 6
19924 : 2016-03-17 00:05:18 : 7
19924 : 2016-03-17 00:05:18 : 8
19924 : 2016-03-17 00:05:18 : 9
19924 : 2016-03-17 00:05:18 : 10
19925 : 2016-03-17 00:05:18 : 11
19925 : 2016-03-17 00:05:18 : 12
19925 : 2016-03-17 00:05:18 : 13
19925 : 2016-03-17 00:05:18 : 14
19925 : 2016-03-17 00:05:18 : 15
这样我们就在进程间共享了$num的数据。
php 的多进程实践的更多相关文章
- python week08 并发编程之多进程--实践部分
一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...
- Pytorch多进程最佳实践
预备知识 模型并行( model parallelism ):即把模型拆分放到不同的设备进行训练,分布式系统中的不同机器(GPU/CPU等)负责网络模型的不同部分 —— 例如,神经网络模型的不同网络层 ...
- Socket编程实践(4) --多进程并发server
1.Socket地址复用 int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); in ...
- 【云计算】使用supervisor管理Docker多进程-ntpd+uwsgi+nginx示例最佳实践
supervisor安装启动: apt-get install supervisor -y # start supervisord nodaemon /usr/bin/supervisord --no ...
- PHP多进程开发与Redis结合实践
原文:https://blog.51cto.com/laok8/2107892?source=drh 业务逻辑介绍: 用户在 APP 上发帖子,然后存储到 Redis 的 List 列表中 利用 Li ...
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- 信息系统实践手记5-CACHE设计一例
说明:信息系统实践手记系列是系笔者在平时研发中先后遇到的大小的问题,也许朴实和细微,但往往却是经常遇到的问题.笔者对其中比较典型的加以收集,描述,归纳和分享. 摘要:此文描述了笔者接触过的部分信息系统 ...
- PHP多进程编程实例
这篇文章主要介绍了PHP多进程编程实例,本文讲解的是在Linux下实现PHP多进程编程,需要的朋友可以参考下 羡慕火影忍者里鸣人的影分身么?没错,PHP程序是可以开动影分身的!想完成任务,又觉得一个进 ...
- 《C++编程规范:101条规则、准则与最佳实践》学习笔记
转载:http://dsqiu.iteye.com/blog/1688217 组织和策略问题 0. 不要为小事斤斤计较.(或者说是:知道什么东西不需要标准化) 无需在多个项目或者整个公司范围内强制实施 ...
随机推荐
- Ubuntu14.04配置jdk1.8.0_25,可切换版本
下载jdk:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 解压: sudo m ...
- 【BZOJ】1013 [JSOI2008]球形空间产生器sphere(高斯消元)
题目 传送门:QWQ 分析 高斯消元就是个大暴力.... 代码 #include <bits/stdc++.h> using namespace std; ; ; int n; doubl ...
- 伯克利推出「看视频学动作」的AI智能体
伯克利曾经提出 DeepMimic框架,让智能体模仿参考动作片段来学习高难度技能.但这些参考片段都是经过动作捕捉合成的高度结构化数据,数据本身的获取需要很高的成本.而近日,他们又更进一步,提出了可以直 ...
- web.py尝试性学习!
首先导入web.py模块! import web 没有的话就: pip install web web.py的URL结构: urls = ( '/', "index" ) 第一部分 ...
- 内置锁(二)synchronized下的等待通知机制
一.等待/通知机制的简介 线程之间的协作: 为了完成某个任务,线程之间需要进行协作,采取的方式:中断.互斥,以及互斥上面的线程的挂起.唤醒:如:生成者--消费者模式.或者某个动作完成,可以唤醒下一 ...
- 温故而知新-PHP文件操作函数
1 文件操作流程 打开文件->读取或者写入文件->关闭文件 fopen->fread,fwrite->fclose fopen可以打开ftp或者http协议的文件,前提示对方支 ...
- HTML5 Canvas ( 图形的透明度和遮盖 ) globalAlpha, globalCompositeOperation
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- centos配置DNS和ip
Centos6.5 永久修改DNS地址的方法 1.配置ip地址文件 /etc/sysconfig/network-scripts/ifcfg-eth0添加一行 DNS1=8.8.8.8 #手动添 ...
- leetcode127
class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordLi ...
- XE 安装后C盘占用太大,C盘空间清理
XE安装完C盘可以清理的垃圾缓存文件 C:\ProgramData\{0DE47792-19BD-4AF4-B9CF-6378FBA44825} XE6 9个G,xe7 18G XE6如此,XE7安 ...