php多进程同步对象--sync扩展

2021-03-22

简介

sync扩展将跨平台同步对象引入PHP。命名和未命名的Mutex,Semaphore,Event,Reader-Writer和命名的Shared Memory对象在POSIX(例如Linux)和Windows平台上提供操作系统级的同步。

在扩展拆卸期间自动清除获取的同步对象。这意味着如果PHP提前终止了脚本(例如超过了脚本执行时间),对象将不会处于未知状态。唯一的例外是当PHP本身崩溃时(例如内部缓冲区溢出)。

未命名同步对象在多线程场景之外没有太多用途。未命名对象与pthreads PECL扩展结合使用更有用

安装

扩展地址:https://pecl.php.net/package/sync

SyncMutex类

互斥锁,将对共享资源(例如文件)的访问限制为单个实例。可计数的互斥锁一次性获取该互斥锁,并在内部跟踪该互斥锁被锁定的次数。互斥锁一旦超出范围,或者解锁的次数与锁定的次数相同,就会被解锁。

互斥锁使用

// 创建互斥锁对象,指定$name时如果$name已存在则必须由运行该进程的当前用户打开该名称,否则将引发异常
$syncMutex = new SyncMutex($name = '');

// 获取SyncMutex对象的排他锁,锁定$wait毫秒(-1为无限制);如果已经获取了锁,则将内部计数器加1
$syncMutex->lock($wait = -1);

// SyncMutex对象的内部计数器减1,当内部计数器达到零时,将释放该对象的实际锁定。$all为true时将内部计数器设置为0,然后释放锁
$syncMutex->unlock($all = false);

SyncSemaphore类

信号量。信号量将对有限资源的访问限制为有限数量的实例中。信号量与互斥锁的不同之处在于,信号量可以一次允许一个以上的实例访问资源,而互斥锁一次只能允许一个实例。

信号量使用

// 创建一个信号量,指定$name时如果$name已存在则必须由运行该进程的当前用户打开该名称,否则将引发异常;
// $initialval为信号量的初始值(就是可以获取的锁的数量),$autounlock为true表示在脚本结束时自动释放信号量
$syncSemaphore = new SyncSemaphore($name = '', $initialval = 1, $autounlock = true);

// 增加SyncSemaphore对象的计数,指定$prevcount时,$prevcount将被赋值为信号量的上一个计数
$syncSemaphore->unlock($prevcount);

// 减少SyncSemaphore对象的计数或等待直到信号量变为非零;$wait毫秒(-1为无限制)为等待信号量的毫秒数
$syncSemaphore->lock($wait = -1);

SyncEvent类

事件对象。自动和手动事件对象均受支持。事件对象在不轮询的情况下等待触发/设置对象。一个实例等待事件对象,而另一个实例触发/设置事件。当长时间运行的进程轮询资源时(例如检查是否需要处理上传的数据),事件对象是有用的。

事件对象使用

// 创建事件对象,指定$name时如果$name已存在则必须由运行该进程的当前用户打开该名称,否则将引发异常;
// $manual为true时必须手动重置事件对象,手动重置事件对象允许所有等待的线程一直进行到重置对象为止
// $prefire为true时预激发(信号)事件对象,仅在调用进程/线程是第一个创建对象的情况下才有影响
$syncEvent = new SyncEvent($name = '', $manual = false, $prefire = false);

// 触发/设置SyncEvent对象,如果事件对象是需要手动重置的,则允许正在等待的多个线程通过
$syncEvent->fire();

// 等待SyncEvent对象被触发,等待事件触发的时间为$wait毫秒(-1为无限制)
$syncEvent->wait($wait = -1);

// 重置已触发/设置SyncEvent对象,仅对手动事件对象有效
$syncEvent->reset();

SyncReaderWriter类

读写器对象。读取器-写入器对象允许多个读取器或一个写入器访问一个资源。这是管理资源的一种有效解决方案,这些资源的访问主要是只读的,但偶尔也需要独占写访问。

读取锁

// 创建读写器对象,指定$name时如果$name已存在则必须由运行该进程的当前用户打开该名称,否则将引发异常;
// $autounlock为true时脚本结束时自动解锁读写器
// 如果一个命名的非自动解锁的读取器写入器,在php脚本结束之后结束,那么底层对象将以不一致的状态结束。
$syncReaderWriter = new SyncReaderWriter($name = '', $autounlock = true);

// 获取SyncReaderWriter对象的读取锁定,锁定时间为$wait毫秒(-1为无限)
$syncReaderWriter = readlock($wait = -1);

// 释放SyncReaderWriter对象的读取锁定
$syncReaderWriter = readunlock();

排他写锁

// 创建读写器对象,指定$name时如果$name已存在则必须由运行该进程的当前用户打开该名称,否则将引发异常;
// $autounlock为true时脚本结束时自动解锁读写器
// 如果一个命名的非自动解锁的读取器写入器,在php脚本结束之后结束,那么底层对象将以不一致的状态结束。
$syncReaderWriter = new SyncReaderWriter($name = '', $autounlock = true);

// 获取SyncReaderWriter对象的排他写锁定,锁定时间为$wait毫秒(-1为无限)
$syncReaderWriter = writelock($wait = -1);

// 释放SyncReaderWriter对象的排他写锁定
$syncReaderWriter = writeunlock();

SyncSharedMemory类

共享内存对象。共享内存使两个单独的进程可以通信,而无需复杂的管道或套接字。命名共享内存是一种替代方法。仍然需要同步对象(例如SyncMutex)来保护共享内存的大多数使用

共享内存使用

// 创建一个名称为$name,$size字节大小的共享内存;如果$name已存在则必须由运行该进程的当前用户打开该名称,否则将引发异常;
$syncSharedMemory = new SyncSharedMemory($name, $size);

// 从$start(字节)位置开始写入数据$string,$string大小超过共享内存大小时数据将被截断,返回写入字节数
// $start为负数时从共享内存结尾处写入
$syncSharedMemory->write($string, $start = 0);

// 读取共享内存中$start开始,$length字节长度的数据
// $start为负时从共享内存结尾处开始读取;$length不指定时读取到共享内存结尾,如果为负则读取到共享内存结尾前$length字节处
$syncSharedMemory->read($start = 0, $length = '');

// 检测SyncSharedMemory对象是否为系统范围内的第一个SyncSharedMemory对象实例
$syncSharedMemory->first();

// 获取SyncSharedMemory对象的字节大小
$syncSharedMemory->size();

 

{/if}