2021-03-18 14:56:35 +08:00
|
|
|
<?php /** @noinspection PhpUnused */
|
2020-11-03 21:02:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace ZM\Store\Lock;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use Swoole\Coroutine;
|
|
|
|
|
use Swoole\Coroutine\System;
|
|
|
|
|
use Swoole\Table;
|
2021-03-27 16:30:15 +08:00
|
|
|
use ZM\Console\Console;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
|
|
|
|
class SpinLock
|
|
|
|
|
{
|
|
|
|
|
/** @var null|Table */
|
|
|
|
|
private static $kv_lock = null;
|
|
|
|
|
|
|
|
|
|
private static $delay = 1;
|
|
|
|
|
|
2021-02-09 17:09:09 +08:00
|
|
|
public static function init($key_cnt, $delay = 1) {
|
2020-11-03 21:02:24 +08:00
|
|
|
self::$kv_lock = new Table($key_cnt, 0.7);
|
|
|
|
|
self::$delay = $delay;
|
|
|
|
|
self::$kv_lock->column('lock_num', Table::TYPE_INT, 8);
|
|
|
|
|
return self::$kv_lock->create();
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 17:09:09 +08:00
|
|
|
public static function lock(string $key) {
|
2020-11-03 21:02:24 +08:00
|
|
|
while (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) { //此资源已经被锁上了
|
2021-02-09 17:09:09 +08:00
|
|
|
if (Coroutine::getCid() != -1) System::sleep(self::$delay / 1000);
|
2020-11-03 21:02:24 +08:00
|
|
|
else usleep(self::$delay * 1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-18 14:56:35 +08:00
|
|
|
public static function tryLock(string $key): bool {
|
2020-11-03 21:02:24 +08:00
|
|
|
if (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function unlock(string $key) {
|
|
|
|
|
return self::$kv_lock->set($key, ['lock_num' => 0]);
|
|
|
|
|
}
|
2021-02-20 16:57:19 +08:00
|
|
|
|
|
|
|
|
public static function transaction(string $key, callable $function) {
|
|
|
|
|
SpinLock::lock($key);
|
|
|
|
|
$function();
|
|
|
|
|
SpinLock::unlock($key);
|
|
|
|
|
}
|
2020-11-03 21:02:24 +08:00
|
|
|
}
|