php 实现锁
在 PHP 中实现锁机制可以通过多种方式,以下是几种常见的方法:
文件锁(flock)
使用 flock 函数可以实现基于文件的锁机制,适用于单机环境。这是一种简单且跨平台的锁实现方式。
$fp = fopen("lockfile.lock", "w+");
if (flock($fp, LOCK_EX)) { // 获取独占锁
// 临界区代码
flock($fp, LOCK_UN); // 释放锁
} else {
echo "无法获取锁";
}
fclose($fp);
Redis 分布式锁
在分布式环境中,可以使用 Redis 实现分布式锁。Redis 的 SETNX 命令(或 SET 命令的 NX 选项)可以实现原子性的锁获取。
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$lockKey = 'resource_lock';
$lockExpire = 10; // 锁的过期时间(秒)
// 尝试获取锁
$isLocked = $redis->set($lockKey, 1, ['nx', 'ex' => $lockExpire]);
if ($isLocked) {
// 临界区代码
$redis->del($lockKey); // 释放锁
} else {
echo "无法获取锁";
}
MySQL 锁
通过 MySQL 的 GET_LOCK 和 RELEASE_LOCK 函数可以实现基于数据库的锁机制。
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$lockName = 'my_lock';
$timeout = 10; // 超时时间(秒)
// 尝试获取锁
$stmt = $pdo->query("SELECT GET_LOCK('$lockName', $timeout)");
$result = $stmt->fetchColumn();
if ($result == 1) {
// 临界区代码
$pdo->query("SELECT RELEASE_LOCK('$lockName')");
} else {
echo "无法获取锁";
}
Semaphore(信号量)
在支持 sysvsem 扩展的环境中,可以使用信号量实现锁机制。

$semKey = ftok(__FILE__, 't');
$semId = sem_get($semKey);
if (sem_acquire($semId)) { // 获取信号量
// 临界区代码
sem_release($semId); // 释放信号量
}
注意事项
- 死锁问题:确保锁最终会被释放,避免因异常导致锁未被释放的情况。
- 锁粒度:根据实际需求选择合适的锁粒度,避免过度加锁影响性能。
- 超时机制:为锁设置合理的超时时间,防止长时间阻塞。
以上方法可以根据实际场景选择使用,文件锁适合单机环境,Redis 和 MySQL 锁适合分布式环境,信号量适合进程间同步。






