php实现锁
PHP 实现锁的方法
在 PHP 中实现锁机制可以通过多种方式,以下是几种常见的方法:
文件锁(flock)
使用 flock 函数可以实现文件锁,适用于单机环境。这是一种简单且有效的锁机制。
$fp = fopen("lockfile.lock", "w+");
if (flock($fp, LOCK_EX)) {
// 执行需要加锁的代码
flock($fp, LOCK_UN); // 释放锁
} else {
// 获取锁失败
}
fclose($fp);
MySQL 锁
通过 MySQL 的 GET_LOCK 和 RELEASE_LOCK 函数可以实现分布式锁。
$pdo = new PDO("mysql:host=localhost;dbname=test", "user", "password");
$stmt = $pdo->prepare("SELECT GET_LOCK('my_lock', 10)");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result["GET_LOCK('my_lock', 10)"] == 1) {
// 执行需要加锁的代码
$stmt = $pdo->prepare("SELECT RELEASE_LOCK('my_lock')");
$stmt->execute();
} else {
// 获取锁失败
}
Redis 锁
Redis 提供了 SETNX 命令,可以实现高效的分布式锁。
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$lockKey = 'my_lock';
$lockValue = uniqid();
$expireTime = 10; // 锁的过期时间(秒)
if ($redis->set($lockKey, $lockValue, ['NX', 'EX' => $expireTime])) {
// 执行需要加锁的代码
if ($redis->get($lockKey) == $lockValue) {
$redis->del($lockKey);
}
} else {
// 获取锁失败
}
Semaphore(信号量)
PHP 的 sem_* 函数系列可以用于实现信号量锁。
$key = ftok(__FILE__, 'a');
$semaphore = sem_get($key);
if (sem_acquire($semaphore)) {
// 执行需要加锁的代码
sem_release($semaphore);
} else {
// 获取锁失败
}
数据库事务锁
在数据库事务中使用 SELECT ... FOR UPDATE 可以实现行级锁。

$pdo = new PDO("mysql:host=localhost;dbname=test", "user", "password");
$pdo->beginTransaction();
$stmt = $pdo->prepare("SELECT * FROM table WHERE id = 1 FOR UPDATE");
$stmt->execute();
// 执行需要加锁的代码
$pdo->commit();
选择锁机制的考虑因素
- 单机环境:文件锁或信号量锁足够。
- 分布式环境:Redis 锁或 MySQL 锁更合适。
- 性能要求:Redis 锁通常性能最佳。
- 锁的粒度:数据库事务锁适用于行级锁定。
每种锁机制都有其适用场景,根据具体需求选择合适的实现方式。






