二十三、Swoole 基础学习笔记 - Swoole 进程间锁 Lock
hi,我是温新,一名PHPer
文章基于 Swoole 5.0.1 版本编写。
**学习目标:学习并了解 Lock 的使用 **
说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!
锁
说起锁,PHP 中有锁,MySQL 中有锁...锁在多进程、多线程操作中有着至关重要的作用。比如有两个进程同时要修改 $num=1
的值,进程一要修改为 5
,进程二要修改为10
,那么$num
最后的值会是多少?这个结果无法确定。可以通过加锁来确保同时只有一个进程对资源进程操作,操作完成后才有由其他进程操作。
Swoole Lock
PHP
代码中可以很方便地创建一个锁,用来实现数据同步。Lock
类支持 5
种锁的类型:
锁类型 | 说明 |
---|---|
SWOOLE_MUTEX | 互斥锁 |
SWOOLE_RWLOCK | 读写锁 |
SWOOLE_SPINLOCK | 自旋锁 |
<?php
// 23-swoole-lock.php
$lock = new Swoole\Lock();
$pool = new Swoole\Process\Pool(3, SWOOLE_IPC_NONE, 0, true);
$pool->on('Workerstart', function ($pool, $workerId) use ($lock) {
echo 'Worker ' . $workerId . '执行 ' . PHP_EOL;
// 加锁
$lock->lock();
echo 'Worker ' . $workerId . ' 获得锁 ' . microtime(true) . PHP_EOL;
sleep(3);
// 释放锁
$lock->unlock();
echo 'Worker ' . $workerId . ' 退出 ' . PHP_EOL;
});
$pool->start();
代码解析:
- 在这一段代码中,使用 3 个进程执行任务;
- 第一个进程进来之后进行加锁,加锁后,其他进程进程会阻塞,知道持有锁的进程执行完成。
执行结果:
$php 23-swoole-lock-1.php
Worker 0 执行
Worker 0 获得锁 1673273562.803
Worker 1 执行
Worker 2 执行
Worker 0 退出
Worker 1 获得锁 1673273565.8035
Worker 0 执行
结果分析:
- 0 ,Worker 0 进来后,获得锁,Worker 1 和 2 出现阻塞操作;
- 3 秒后,Worker 0 执行完成,然后 Worker 获得锁,然后其他 Worker 继续阻塞。
Lock 相关方法
__contruct
/**
* @param int $type 锁的类型
* @param string $lockfile 指定文件锁的路径【当类型为 SWOOLE_FILELOCK 时必须传入】
**/
Swoole\Lock::__construct(int $type = SWOOLE_MUTEX, string $lockfile = '');
注意:
1、不要循环创建 / 销毁锁的对象,否则会发生内存泄漏;
2、每一种类型的锁支持的方法都不一样。如读写锁、文件锁可以支持
$lock->lock_read()
。另外除文件锁外,其他类型的锁必须在父进程内创建,这样fork
出的子进程之间才可以互相争抢锁。
lock
含义:加锁操作。如果有其他进程持有锁,那这里将进入阻塞,直到持有锁的进程 unlock()
释放锁。
Swoole\Lock->lock(): bool
unlock
含义:释放锁。
Swoole\Lock->unlock(): bool
lock_read
含义:只读加锁。
Swoole\Lock->lock_read(): bool
- 在持有读锁的过程中,其他进程依然可以获得读锁,可以继续发生读操作;
- 但不能
$lock->lock()
或$lock->trylock()
,这两个方法是获取独占锁,在独占锁加锁时,其他进程无法再进行任何操作,包括读锁; - 当另一个进程获得独占锁 (调用
$lock->lock()
/$lock->trylock()
) 时,$lock->lock_read()
会发生阻塞,直到持有独占锁的进程释放锁。
只有
SWOOLE_RWLOCK
和SWOOLE_FILELOCK
类型的锁支持只读加锁
trylock_read()
含义:加锁。此方法与 lock_read()
相同,但是非阻塞的。
Swoole\Lock->trylock_read(): bool
调用会立即返回,必须检测返回值以确定是否拿到了锁。
lockwait
含义:加锁操作。作用与 lock()
方法一致,但 lockwait()
可以设置超时时间。
/**
* @param float $timeout 指定超时时间
*
* @return 1、在规定的时间内未获得锁,返回 false
* 2、加锁成功返回 true
**/
Swoole\Lock->lockwait(float $timeout = 1.0): bool
本篇文章学习了 Lock 的值,下篇文章继续学习 Swoole。
请登录后再评论