ホームページ  >  記事  >  バックエンド開発  >  PHPプロセス通信のセマフォを簡単に理解する

PHPプロセス通信のセマフォを簡単に理解する

WBOY
WBOY転載
2022-09-02 16:57:222113ブラウズ
# (推奨チュートリアル:

PHP ビデオ チュートリアル)

一般的なプロセス通信方法

##理論的根拠

    重要なリソース: 一度に 1 つのプロセスのみがアクセスを許可されるリソース。
  • クリティカル セクション: 各プロセスの重要なリソースにアクセスするコードをクリティカル セクションと呼びます
いわゆるクリティカル セクション (クリティカル セクションとも呼ばれます) は、プロセスにアクセスしてアクセスするコードです。共有データ部分を操作します。

プロセスは相互に排他的です: 2 つ以上のプロセスが、同じ共有変数セットのクリティカル領域に同時に入ることはできません。つまり、1 つのプロセスがクリティカルなリソースにアクセスしており、他のプロセスはアクセスしなければ待機する必要があります。アクセスしたいです。

プロセスの同期: 主に、複数のプロセス間の実行順序を決定し、データ競合の問題を回避する方法、つまり、複数のプロセスをうまく連携させる方法を研究します。

いわゆる同期、つまり、同時プロセス/スレッドは、いくつかの重要なポイントで相互に待機し、メッセージを交換する必要がある場合があります。この相互に制限された待機と情報交換は、プロセス/スレッドの同期と呼ばれます。

人生における同期の例を挙げると、あなたはお腹が空いて何か食べたいと思っています。あなたは母親に早く料理をするように頼みます。それを聞いて母親は料理を始めますが、母親が料理を終える前にあなたはブロックしなければなりませんと待って、お母さんが料理を終えたら、自然に通知が来て、それから食事を始めることができます。

同期と相互排他は 2 つの異なる概念であることに注意してください:

同期は次のようなものです: 「操作 A は操作 B の前に実行する必要がある」、「操作 C は操作 A と操作 B の前に実行する必要がある」 「すべてが完了した後にのみ実行できます」など;

相互排他は次のようなものです: 「操作 A と操作 B を同時に実行することはできません」;

システム V セマフォ

セマフォの目的: 主に、パブリック リソース オブジェクトへのマルチプロセスまたはマルチスレッドのアクセス制御に使用されます。ロックと同様にマルチプロセス(マルチスレッド同期)の問題を解決するために使用され、アクセス前にロックを取得(取得できていない場合は待機)し、アクセス後にロックを解放します。

複数のプロセス/マルチスレッドは通常、同時に実行されます。パブリック リソースへのアクセスが同期されていない場合、データ損傷が発生しやすくなります。

セマフォは実際には整数カウンターであり、主に相互実装に使用されます。プロセス間通信のためにデータをキャッシュする代わりに、プロセス間の排他と同期を行います。

セマフォはリソースの数を表します。セマフォを制御するには 2 つのアトミック操作があります:

1 つは P 操作です。この操作はセマフォから -1 を減算します。減算後、セマフォ = 0 の場合、使用可能なリソースがまだ存在し、プロセスが通常どおり実行を継続できることを示します。

もう 1 つは V 操作です。この操作ではセマフォに 1 が追加されます。追加後、セマフォ 0 の場合、現在ブロックされているプロセスがないことを示します;

P 操作は共有リソースに入る前に使用され、V 操作は共有リソースから出た後に使用されます。これら 2 つの操作はペアで指定する必要があります。

たとえば、2 つのリソースのセマフォは 2 つの列車の線路に相当し、PV の動作プロセスは次のようになります。これはセマフォの P 操作、リソース -1 に相当するため、トラックは 1 つだけ残っています。

次に、別のトレインが別のトラックを占有します。これが P 操作、リソース -1 です。

#利用可能な線路がないため、この時点で信号が赤に変わり、3 番目の列車を待たなければなりません

##最初の列車が線路を出発します。これは V 運転に相当します。このとき、線路リソースは 1 で、信号は青に変わります。

3 番目の列車は、渋滞を発見しました。信号が青に変わり、線路に入ると線路のリソースが使い果たされて 0 になり、信号が赤に変わります

この鉄道軌道システムでは、線路は公共資源であり、各列車は糸のようなものであり、信号機は信号機の役割を果たします。セマフォは、ロックの相互排他操作を実現でき、プロセス/スレッドの同期も実現できます。

セマフォの種類

1) バイナリ セマフォ (バイナリ セマフォとも呼ばれます)

このとき、セマフォの初期値は 0 と 1 のみです。 (バイナリ セマフォはミューテックス ロック操作を実装できます)

2) 一般/カウント セマフォ

現時点では、セマフォの初期値は負でない任意の数値にすることができます。明らかに、バイナリ セマフォが含まれています。上記の列車線路の例は、カウント セマフォを使用して実装できます。一般に、カウント セマフォとロックの違いは、複数のスレッド/プロセス (スレッドの数はカウント セマフォの初期値によって定義されます) が許可されることです。パブリックリソースを同時に操作する

通常、複数のプロセスを開発する場合にのみ、セマフォの使用が必要なシナリオに遭遇することがありますが、phper ではセマフォを使用するシナリオはほとんどありません。相互に排他的な操作

php はパブリック リソースのマルチプロセス操作をシミュレートします

<?php
$file = "num.txt";//定一个空文件
$count =0;
file_put_contents($file,$count);

$pid = pcntl_fork();//fork 一个进程

if($pid == 0){//子进程执行逻辑
    $x = (int)file_get_contents($file);//读取文件内容
    //i 循环累加
    for($i=0; $i<1000; $i++){
        $x = $x + 1;
    }
    //写入文件
    file_put_contents($file,$x);
    //子进程退出
    exit(0);
}
//父进程执行逻辑
$x = (int)file_get_contents($file);
for($i=0; $i<1000; $i++){
    $x = $x+1;
}
//累加写入
file_put_contents($file,$x);

シェル スクリプトの作成を支援します

#!/bin/bash
for a in {1..1000}
do
    (php demo1.php)
    b=`cat num.txt`
    if [ $b != 2000 ]
    then
        echo -e "错误$b"
    fi
done

論理的につまり、変数 #$x は最後に書き込まれます。入力ファイルの値は 2000 であるはずですが、残念ながらそうではありません。上記のスクリプトを実行してみましょう:

# 1000 回実行した後、変数 $x が出現したことがわかりました。値の結果は 8 回 1000 でした。エラーの可能性は比較的小さいですが、コンピューターでは許容できません。

なぜこのようなことが起こるのでしょうか? シングルコア CPU システムで複数のプログラムが同時に実行されているような錯覚を実現するために、オペレーティング システムは通常、タイム スライス スケジューリングを使用することがわかっています。実行すると、高級言語ではコードのすべての行がアトミックになるわけではありません。たとえば、

x = (int)file_get_contents($file) このコード行は私たちには不可能です セグメンテーションはアトミックですが、コンパイラがそれをアセンブリ コード [機械語] にコンパイルした後、複数の命令によって実装される可能性があります。命令の半分だけがセグメンテーションされると問題が発生します。プロセスによって割り当てられたタイム スライスが使い果たされるか、他のプロセスによって中断されるまで実行されます。データ損傷が発生し、最終的な計算結果にエラーが発生する可能性があります。

php を使用してシステム v セマフォ セット関数をカプセル化します

<?php
$file = "num.txt";//定一个空文件
$count =0;
$key = ftok("demo1.php","x");
$sem_id = sem_get($key,1);// 第二个参数是个整数,表示设置信号量集,设置为1 把它当做二值信号量来用,用于互斥
file_put_contents($file,$count);
$pid = pcntl_fork();//fork 一个进程
if($pid == 0){//子进程执行逻辑
sem_acquire($sem_id); // P -1 操作 获取一个信号量 , 如果为0表示资源被占用进程挂起等待信号量释放
    $x = (int)file_get_contents($file);//读取文件内容
    //i 循环累加
    for($i=0; $i<1000; $i++){
        $x = $x + 1;
    }
    //写入文件
    file_put_contents($file,$x);
       sem_release($sem_id); //V +1 操作 释放信号量
    //子进程退出
    exit(0);
}
//父进程执行逻辑
sem_acquire($sem_id); // P -1 操作  获取信号量, 如果为0表示资源被占用进程挂起等待信号量释放
$x = (int)file_get_contents($file);
for($i=0; $i<1000; $i++){
    $x = $x+1;
}
//累加写入
file_put_contents($file,$x);
sem_release($sem_id); //V +1 操作 释放信号量

セマフォを追加した後は、100% 2000 であることが保証されなければなりません。他の値は絶対に表示されません。

(推奨チュートリアル:

PHP ビデオ チュートリアル)

以上がPHPプロセス通信のセマフォを簡単に理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjb51.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。