考虑PHP脚本(可能在其他脚本中调用函数)。我想确保它的某些部分一次只能由一个请求执行。例如:
doSomething();
doSomethingElse(); // Lock this: Can only be executed by one request at a time
yetAnotherThing();
因此,如果请求A当前在'doSomethingElse()
内,我希望在调用此函数的代码行之前将任何更远的请求排队。
我还没有在网上找到这个解决方案,因为我说的是请求之间的锁定,而不是对作为同一请求的一部分执行的单独线程的锁定。我正在使用Apache服务器。
答案 0 :(得分:1)
您需要通过设置一个标志来指示应该发生或不发生的事情来保护执行。
您可以将guard-status存储在任何其他存储中,这些存储在请求中是持久的:数据库,会话,平面文件......
你可以做的最基本的事情就是写一个标志文件。
当文件存在时,这将排除处理doSomethingElse()
的所有后续请求。但是,当文件消失时,下一个请求将再次执行doSomethingElse()
。
您可以使用flock()
(http://php.net/manual/en/function.flock.php)
或者你自己的平面文件锁定方法。仅仅是为了这个概念:
添加file_put_contents(__DIR__.'/doSomethingElse.processing.flag', 'processing');
在doSomethingElse()
的开头,并在函数末尾删除它。
然后将执行包装成条件检查:
doSomething();
if( ! is_file(__DIR__.'/doSomethingElse.processing.flag')) {
doSomethingElse();
}
yetAnotherThing();
构建队列
那么,您可以扩展给定的想法或使用准备好的库/工具来完成工作。
建立"队列"你需要扩展锁定理念并且:
队列锁定要处理的资源,并且只允许最低的ID。 锁通常被称为信号量。 (它实际上可能是最高的ID,取决于您的处理逻辑 - 它基本上是LIFO或FIFO堆栈处理。)
创建队列并将作业放入,然后添加作为cronjob或守护程序运行的worker。工作人员从队列中取出作业,处理它并返回结果,并带有状态标志" done"。然后,您可以定期轮询队列以查看作业是否已完成。您可以使用数据库作为队列,选择一个支持锁定的数据库。
while(1) {
begin new transaction;
remove item from queue;
process item;
save new state of item;
commit;
}
不确定你的目标,但你有很多选择来实现它:
对于基于文件的队列机制,请参阅此基本教程:http://squirrelshaterobots.com/programming/php/building-a-queue-server-in-php-part-1-understanding-the-project/
您可以依赖SPLQueue并将其与锁定理念相结合。
PHP也支持信号量:http://php.net/manual/en/ref.sem.php
然后有真正的作业队列系统,如Gearman,Beanstalk,Redis或任何消息队列,如RabbitMQ,ZeroMQ。
答案 1 :(得分:0)
您可以将doSomethingElse()函数放在另一个文件中,然后可以使用
flock
http://php.net/manual/en/function.flock.php 此功能用于防止同时访问。