/**
* テスト書き込みロック
* スレッド 1 を開く
*/
require("file_lock.php");
$lock = new File_Lock(dirname(dirname(__FILE__)) . "/FileLock.lock");
/**単一スレッドのロック速度は 1 秒あたり 30,000 回です。 **/
/**2 つのスレッドで 20,000 データを書き込み、約 7 秒かかります*/
/**1 スレッドで 10,000 データを書き込むのにかかる時間は約 3.9 秒です。実際には 2 つのファイルが同時に書き込まれるため、より高速になります。*/
/**ロックしない場合、プロセスの書き込みには約 2.8 秒かかります。ロックには代償が伴います。*/
/**ロックがないと、2 つのプロセスの分散はあまり均等ではなくなり、ほとんどのプロセスが競合します。*/
$lock-> ;writeLock();
$lock->increment();
$lock->unlock();
while ($lock->get() < 2) {
usleep(1000);
}
睡眠(1);
echo "n の実行を開始します";
$t1 = マイクロタイム(true);
for ($i = 0; $i <10000; $i++)
{
$lock->writeLock();
$lock->increment(1);
$lock->unlock();
}
$t2 = microtime(true) - $t1;
エコー $t2;
?>
class File_Lock
{
private $name;
プライベート $ハンドル;
プライベート$モード;
function __construct($filename, $mode = 'a+b')
{
global $php_errormsg;
$this->name = $filename;
$path = dirname($this->name);
if ($path == '.' || !is_dir($path)) {
global $config_file_lock_path;
$this->name = str_replace(array("/", ""), array("_", "_"), $this->name);
if ($config_file_lock_path == null) {
$this->name = dirname(__FILE__) 。 "/ロック/" 。 $this->名前;
} else {
$this->name = $config_file_lock_path 。 「/」。 $this->名前;
}
}
$this->mode = $mode;
$this->ハンドル = @fopen($this->name, $mode);
if ($this->handle == false) {
新しい例外をスロー($php_errormsg);
}
}
パブリック関数 close()
{
if ($this->handle !== null ) {
@fclose($this->handle);
$this->ハンドル = null;
}
}
パブリック関数 __destruct()
{
$this->close();
}
パブリック関数 lock($lockType, $nonBlockingLock = false)
{
if ($nonBlockingLock) {
return flock($this->handle, $lockType | LOCK_NB);
} else {
return flock($this->handle, $lockType);
}
}
パブリック関数 readLock()
{
return $this->lock(LOCK_SH);
}
パブリック関数 writeLock($wait = 0.1)
{
$startTime = microtime(true);
$canWrite = false;
do {
$canWrite = flock($this->ハンドル, LOCK_EX);
if(!$canWrite) {
usleep(rand(10, 1000));
}
} while ((!$canWrite) && ((microtime(true) - $startTime) < $wait));
}
/**
* マルチスレッドシステムで番号を記録したくない場合は、
* ロックを開いて、+ MOD を使用してください。ファイルを fopen してもデータは
* 破壊されません。
*
* この関数は、delt 値をインクリメントし、ファイルに保存します。
*
* @param int $delt
* @return int
*/
public function increment($delt = 1)
{
$n = $this->get();
$n += $delt;
$this->set($n);
$n を返します;
}
パブリック関数 get()
{
fseek($this->handle, 0);
return (int)fgets($this->handle);
}
パブリック関数 set($value)
{
ftruncate($this->handle, 0);
return fwrite($this->handle, (string)$value);
}
パブリック関数unlock()
{
if ($this->handle !== null ) {
return flock($this->handle, LOCK_UN);
} else {
true を返します。
}
}
}
?>