首页 > 开发 > PHP > 正文

PHP程序中的文件锁、互斥锁、读写锁使用技巧解析

2024-05-04 22:31:43
字体:
来源:转载
供稿:网友

文件锁
全名叫 advisory file lock, 书中有提及。 这类锁比较常见,例如 mysql, php-fpm 启动之后都会有一个pid文件记录了进程id,这个文件就是文件锁。

这个锁可以防止重复运行一个进程,例如在使用crontab时,限定每一分钟执行一个任务,但这个进程运行时间可能超过一分钟,如果不用进程锁解决冲突的话两个进程一起执行就会有问题。

使用PID文件锁还有一个好处,方便进程向自己发停止或者重启信号。例如重启php-fpm的命令为

kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
发送USR2信号给pid文件记录的进程,信号属于进程通信,会另开一个篇幅。

php的接口为flock,文档比较详细。先看一下定义,bool flock ( resource $handle , int $operation [, int &$wouldblock ] ).

$handle是文件系统指针,是典型地由 fopen() 创建的 resource(资源)。这就意味着使用flock必须打开一个文件。 $operation 是操作类型。 &$wouldblock 如果锁是阻塞的,那么这个变量会设为1.

需要注意的是,这个函数默认是阻塞的,如果想非阻塞可以在 operation 加一个 bitmask LOCK_NB. 接下来测试一下。

$pid_file = "/tmp/process.pid";$pid = posix_getpid();$fp = fopen($pid_file, 'w+');if(flock($fp, LOCK_EX | LOCK_NB)){  echo "got the lock /n";  ftruncate($fp, 0);   // truncate file  fwrite($fp, $pid);  fflush($fp);      // flush output before releasing the lock  sleep(300); // long running process  flock($fp, LOCK_UN);  // 释放锁定} else {  echo "Cannot get pid lock. The process is already up /n";}fclose($fp);

保存为 process.php,运行php process.php &, 此时再次运行php process.php,就可以看到错误提示。flock也有共享锁,LOCK_SH.

互斥锁和读写锁
sync模块中的Mutex:
Mutex是一个组合词,mutual exclusion。用pecl安装一下sync模块, pecl install sync。 文档中的SyncMutex只有两个方法,lock 和 unlock, 我们就直接上代码测试吧。没有用IDE写,所以cs异常丑陋,请无视。

$mutex = new SyncMutex("UniqueName");for($i=0; $i<2; $i++){  $pid = pcntl_fork();  if($pid <0){    die("fork failed");  }elseif ($pid>0){    echo "parent process /n";  }else{    echo "child process {$i} is born. /n";    obtainLock($mutex, $i);  }}while (pcntl_waitpid(0, $status) != -1) {   $status = pcntl_wexitstatus($status);   echo "Child $status completed/n"; }function obtainLock ($mutex, $i){  echo "process {$i} is getting the mutex /n";  $res = $mutex->lock(200);  sleep(1);  if (!$res){    echo "process {$i} unable to lock mutex. /n";  }else{    echo "process {$i} successfully got the mutex /n";    $mutex->unlock();  }  exit();}

保存为mutex.php, run php mutex.php, output is

parent process parent process child process 1 is born. process 1 is getting the mutex child process 0 is born. process 0 is getting the mutex process 1 successfully got the mutex Child 0 completedprocess 0 unable to lock mutex. Child 0 completed            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表