php多プロセスシミュレーションを同時に行うことによって発生した問題のまとめ


前言
本論文では、実例コードを通じて、php多プロセスのシミュレーションと合併に関する問題を紹介します。皆さんの参考にして勉強するために、以下の話は多くなくなりました。詳しい紹介を見てみましょう。

drop table if exists `test`;
create table if not exists `test` (
 id int not null auto_increment , 
 count int default 0 , 
 primary key `id` (`id`)
) engine=innodb character set utf8mb4 collate = utf8mb4_bin comment '   ';

insert into test (`count`) values (100);
phpコード

//     
$pro_count = 100;
$pids = [];
for ($i = 0; $i < $pro_count; ++$i)
{
 $pid = pcntl_fork();
 if ($pid < 0) {
  //    
  throw new Exception('       : ' . $i);
 } else if ($pid > 0) {
  //    
  $pids[] = $pid;
 } else {
  //    
  try {
   $pdo = new PDO(...);
   $pdo->beginTransaction();
   $stmt = $pdo->query('select `count` from test');
   $count = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
   $count = intval($count);
   if ($count > 0) {
    $count--;
    $pdo->query('update test set `count` = ' . $count . ' where id = 2');
   }
   $pdo->commit();
  } catch(Exception $e) {
   $pdo->rollBack(); 
   throw $e;
  }
  //      
  exit;
 }
}
期待の結果
countフィールドの減少が期待される量は100を超えて、マイナスになります。つまりマイナス!
実際の結果
200を併発した場合、複数回運転した結果、それぞれ以下のようになります。
1.count=65
2.count=75
3.count=55
4.count=84

期待した結果とはずいぶん違います。なぜこのような現象が現れましたか?
説明
まず、現在のプログラムの実行環境を明確にし、同時にシーンを作る。同時進行とは、ほぼ同時に実行することを合併といいます。具体的な説明は以下の通りです。
プロセスの更新
1−40は同時に100 99を作成して実行する。
41-80を同時に作成して実行します。99 98
81-100を同時に作成して実行します。98
上記の第1行について説明します。第1-40サブプロセスの作成はほぼ同時に実行もほぼ同時に行われます。
プロセス1はcount=100を取得し、99を更新する。
プロセス2はcount=100を取得し、99を更新する。

プロセス40はcount=100を取得し、99を更新する。
したがって、実際には、これらのプロセスは同じ操作をしていますが、予想通りには行われていません。プロセス1はcount=100を取得し、99を更新します。プロセス2は、プロセス1の更新結果count=99を取得し、98を更新する。プロセス99は、プロセス98の更新後の結果count=1を取得し、0を更新する。
発生する現象は減少しました!
結論
上記の方法で実現したプログラムを採用して、在庫は常に>=0です。
疑問
超在庫をシミュレートするシーンはどうやってプログラムを設計しますか?
上記のコードを使用しています。以下のコードを使用します。

if ($count > 0) {
 $count--;
 $pdo->query('update test set `count` = ' . $count . ' where id = 2');
}
次のように修正します。

if ($count > 0) {
 $pdo->query('update test set `count` = `count` - 1 where id = 2');
}
結果的に超在庫が出てきます!
在庫100、同時に200、最終在庫は-63に減少しました。なぜこのような状況が発生しましたか?以下にプログラム運転の具体的な手順を説明します。
プロセス1は在庫100を取得し、99を更新する。
プロセス2は在庫100を取得し、98(99−1)を更新する。
プロセス3は在庫100を取得し、97(98−1)を更新する。

プロセス168は在庫1を取得し、0を更新する(1−1)
プロセス169は在庫1を取得し、更新-1(0-1)
プロセス170は在庫1を取得し、更新-2(-1-1)

プロセス200は在庫1を取得し、更新-63(-62-1)
今はとてもぼんやりしていますが、実際には次のような文があります。

$pdo->query('update test set `count` = `count` - 1 where id = 2');
ここでプロセス1を詳しく説明します。略してaと言います。プロセス2、略してb彼らの具体的な実行順序:
1.a在庫100を照会する
2.b在庫100を照会しました。
3.a在庫を更新するのは99(100-1)です。これは秒でわかるはずです。
4.b在庫更新98(99-1)
-b更新操作を実行する時に持ってきたのはa更新後の在庫です。
-なぜですか?更新文は‘update test set count=count-1 where id=2`。
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考となる学習価値を持っています。質問があれば、メッセージを書いて交流してください。ありがとうございます。