2016-04-14 33 views
3

我需要在PHP中有一个互斥方法,以便通过变量值保持排他性。这就是说,具有相同值的线程应该每次输入一个方法,而具有不同值的线程可以任意访问该方法。如何在PHP中创建每个变量值的互斥方法

例如,给定该方法:

/** 
* @param integer $value 
*/ 
function mutexMethod($value) 
{ 
    // Lock for value $value 
    echo 'processing'; 
    sleep(2); 
    echo 'this is so heavy'; 
    // Unlock for value $value 
} 

例如(我需要这通过Apache运行):

time | 
0 | php > mutexMethod(1); | php > mutexMethod(2); | php > mutexMethod(1); 
1 | processing   | processing   | 
2 |      |      | 
3 | this is so heavy  | this is so heavy  | processing 
4 |      |      | 
5 |      |      | this is so heavy 

作为第一溶液中,我使用semaphores尝试,但因为$value可能会得到任何值,所以我已经很快用完了信号量空间(我试过在使用它们后删除信号量,但是这会中断其他线程,因为我不知道是否有任何线程在等待它们,我不能删除他们的任意随手。

作为第二种解决方案,我尝试创建一个值为$value的文件作为名称,并使用flock来锁定其他任何线程。尽管这在CLI中有效,但我无法通过apache设置它。它当然锁定了文件,但它从未释放该锁,所以其他任何请求都会卡住,直到第一个请求超时(30秒后)。

最后我虽然关于使用MySQL锁,但我想尽量避免它们,因为我们不希望将MySQL实例用于这种事情。理想情况下,我们需要一个纯PHP解决方案。

你有什么想法解决这个问题吗?我想避免使用单信号量解决方案(比如有一个单一的信号量来控制对跟踪锁的文件的访问),因为这会造成巨大的瓶颈(特别是对于具有不同值的线程)。

非常感谢。

+0

你能详细解释你正在解决的更广泛的问题吗?从我所看到的情况来看,可能的解决方案可能是将值存储在一个集合中,并创建存取函数,以便线程必须获取互斥锁才能修改集合成员资格。这样,你将有一个线程同步的方式来“签出”和“签入”$ value's。 – aednichols

+0

我试图解决网络上的竞争条件,以便用户触发算法来为具有ID的对象执行一些计算(相对昂贵和耗时)。所以我们的想法是,根据这个ID,“排队”或简单地阻止请求并逐一处理它们。如果我允许同一个ID同时执行请求,我可能会放弃以前的计算。问题是,对不同ID的请求可以同时执行而没有任何缺点。 – carlosV2

+0

每个特定ID的计算结果是否相同?听起来像你应该考虑[记忆](https://en.wikipedia.org/wiki/Memoization) – aednichols

回答

0

https://github.com/arvenil/ninja-mutex

羊群/ mysql /下的Redis /内存缓存适配器

您可以尝试所有这些,挑选适合工作的一个你

在你的案例看起来是这样的

<?php 
require 'vendor/autoload.php'; 

use NinjaMutex\Lock\MemcacheLock; 
use NinjaMutex\MutexFabric; 

$memcache = new Memcache(); 
$memcache->connect('127.0.0.1', 11211); 
$lock = new MemcacheLock($memcache); 
$mutexFabric = new MutexFabric('memcache', $lock); 
if ($mutexFabric->get($value)->acquireLock(1000)) { 
    // Do some very critical stuff 

    // and release lock after you finish 
    $mutexFabric->get($value)->releaseLock(); 
} else { 
    throw new Exception('Unable to gain lock for very critical stuff!'); 
}