2016-04-14 18 views
3

PHPでmutexメソッドを使用して、排他性を可変値で保持する必要があります。これは、同じ値を持つスレッドは一度に1つずつそのメソッドに入るべきですが、異なる値を持つスレッドはそのメソッドに任意にアクセスできます。例えば変数値ごとにPHPでミューテックスメソッドを作成する方法

は、その方法所与:例えば

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

(Iは、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 

を、Iはsemaphoresを使用して試みたが、 $valueは値を得ることができるので、私はセマフォスペースを非常にすばやく使い果たしました(セマフォを使用した後にセマフォを削除しようとしましたが、これは他のスレッドを待っています。私はそれらを自由に取り除くことができないily。

2番目の解決策として、名前として$valueの値を持つファイルを作成し、flockを使用して他のスレッドをロックしようとしました。これがCLIで動作したにもかかわらず、私はそれがApacheを介して動作するように管理できませんでした。それは確実にファイルをロックしましたが、そのロックを解放したことはありませんので、最初のタイムアウト(30秒後)が経過するまで他の要求がスタックされました。

最後に、私はMySQLのロックを使用していましたが、そのようなことに対してMySQLインスタンスを使用したくない程度にそれらを避けたいと思います。理想的には、純粋なPHPソリューションを希望します。

この問題を解決するにはどうすればよいですか?私は単一のセマフォーの解決策(ロックを追跡するファイルへのアクセスを制御するために単一のセマフォーを持つようなもの)を避けたいと思っています(特に異なる値のスレッドのために)。

ありがとうございました。

+0

あなたが解決しているより広い問題について詳しく説明できますか?私が見ることができるのは、値をセットに格納し、セットメンバーシップを変更するためにスレッドがmutexを取得する必要があるようなアクセサ関数を作成することです。こうすることで、スレッドが '$ value'を"チェックアウト "して"チェックイン "する同期化された方法が得られます。 – aednichols

+0

私は、Web上で競合状態を解決しようとしているため、IDを持つオブジェクトに対して計算を実行するアルゴリズム(比較的高価で時間がかかる)をユーザーがトリガーしています。つまり、このIDに基づいて、リクエストを「キューに入れる」か、単にブロックして、それを1つずつ処理することです。私が同じIDに対して同時にリクエストを実行できるようにすると、私は前の計算を失う可能性があります。ただし、異なるIDの要求は、何の欠点もなく同時に実行できるということです。 – carlosV2

+0

特定のIDの計算結果は毎回同じですか?あなたは[memoization](https://en.wikipedia.org/wiki/Memoization)を考慮する必要があります。 – aednichols

答えて

0

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

群れ/ mysqlの/ Redisの/ memcacheのアダプタ

あなたはそれらすべてを試してみてのために働くものを選ぶことができます。この

<?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!'); 
} 
ようになり、あなたの場合の例で

関連する問題