PHP pthreads v3 동기 화 처리 synchronized 용법 예시

이 사례 는 PHP pthreads v3 에서 동기 화 처리 synchronized 용법 을 다 루 었 다.여러분 께 참고 하도록 공유 하 겠 습 니 다.구체 적 으로 는 다음 과 같 습 니 다.
동기 화 를 사용 하 는 이 유 는 여러 스 레 드 에서 같은 자원 을 조작 할 때 혼란 이 발생 하기 때문이다.
예 를 들 어 두 개의 스 레 드 가 변 수 를 1 로 조작 하고 첫 번 째 스 레 드 가 아직 오지 않 았 을 때 두 번 째 스 레 드 는 변 수 를 조작 했다.그 변수의 최종 결 과 는 알 수 없 는 것 이 고 이 럴 때 동기 화 되 어 제어 해 야 한다.
예 는 다음 과 같다.

<?php
class Count extends Thread
{
  public $cnt = 0;

  public function run()
  {
    $this->add();
  }

  public function add()
  {
    //      1  
    for ($i = 0; $i < 100000; $i++) {
      ++$this->cnt;
    }
  }
}

$c = new Count();
//  start() ,  run()     add()  
$c->start();
//         add()  ,        for   $cnt    
$c->add();
//            ,             
$c->join();

//           
var_dump($c->cnt);
여러 번 실 행 된 후$cnt 의 값 은 확실 하지 않 습 니 다.다음 그림 에서 보 듯 이:

pthreads v2 에서 우 리 는 Mutex 를 사용 할 수 있 지만 v3 버 전에 서 삭제 되 었 기 때문에 우 리 는 간단하게 1 을 더 해서 synchronized 에 동기 화 할 수 있 습 니 다.코드 는 다음 과 같 습 니 다.

<?php
class Count extends Thread
{
  public $cnt = 0;

  public function run()
  {
    $this->add();
  }

  public function add()
  {
    $this->synchronized(function () {
      //      1  
      for ($i = 0; $i < 100000; $i++) {
        ++$this->cnt;
      }
    });
  }
}

$c = new Count();
//  start() ,  run()     add()  
$c->start();
//         add()  ,        for   $cnt    
$c->add();
//            ,             
$c->join();

//        200000
var_dump($c->cnt);
결 과 는 다음 과 같다.

물론 우 리 는 notify()와 wait()를 통 해 동기 화 제어 할 수 있 습 니 다.코드 는 다음 과 같 습 니 다.

<?php
class Task extends Thread
{
  public $flag = 1;

  public function run()
  {
    $this->synchronized(function () {
      //    1     
      if ($this->flag !== 1) {
        $this->wait();
      }

      for ($i = 1; $i <= 10; $i++) {

        echo "flag : {$this->flag} i : {$i} 
"; if ($this->flag === 1) { // $this->flag = 2; // , // ,notify() wait() , $this->notify(); $this->wait(); } } // notify() // flag : 2 i : 20 , i 11 , for , // wait() , , notify() $this->notify(); }); } } $t = new Task(); $t->start(); $t->synchronized(function ($obj) { // 2 if ($obj->flag !== 2) { $obj->wait(); } for ($i = 11; $i <= 20; $i++) { echo "flag : {$obj->flag} i : {$i}
"; if ($obj->flag === 2) { $obj->flag = 1; $obj->notify(); $obj->wait(); } } }, $t); // , $t->join();
결 과 는 다음 그림 과 같다.

저 희 는 notify()와 wait()를 통 해 두 개의 for 순환 을 제어 하고 왔 다 갔다 하 는 출력 변수 i 의 값 을 제어 하여 순서 성 을 확보 합 니 다.
우 리 는 복잡 한 예 를 하나 더 살 펴 보 겠 습 니 다.공 유 된 자원 은 동기 화 작업 을 하지 않 으 면 예측 할 수 없 는 상황 이 발생 할 수 있 습 니 다.코드 는 다음 과 같 습 니 다. 

<?php
class Task extends Thread
{
  private $name;
  private $file;

  public function __construct($name, $file)
  {
    $this->name = $name;
    $this->file = $file;
  }

  public function run()
  {
    $data = file_get_contents($this->file);
    $data = floatval($data);
    for ($i = 0; $i < 100000; $i++) {
      ++$data;
    }
    file_put_contents($this->file, $data);
    echo "task : {$this->name} data : {$data} 
"; } } $tasks = []; $file = './test.log'; for ($i = 0; $i < 100; $i++) { $tasks[$i] = new Task($i, $file); $tasks[$i]->start(); } for ($i = 0; $i < 100; $i++) { $tasks[$i]->join(); }
우 리 는 100 개의 스 레 드 를 열 어 파일 test.log 를 읽 고 씁 니 다.이상 적 인 상태 에서 test.log 의 데 이 터 는 매번 1000000 을 증가 해 야 합 니 다.현재 의 컴퓨터 설정 이 모두 비교적 좋 으 니,모두 몇 번 더 실행 하면 효 과 를 볼 수 있다.

 마지막 데이터 가 20000 이 부족 한 것 같 습 니 다.다 중 스 레 드 에서 test.log 파일 을 읽 고 쓰 는 것 이 분명 합 니 다.우 리 는 자 물 쇠 를 추가 하지 않 았 기 때문에 데이터 가 혼 란 스 러 울 것 입 니 다.
지금 우 리 는 코드 를 수정 합 니 다.다음 과 같 습 니 다.

<?php
class File extends Thread
{
  private $file;

  public function __construct($file)
  {
    $this->file = $file;
  }

  public function inc()
  {
    //      , 100 task    inc   ,synchronized             
    //  ,  ,   inc    Task ,       ,    task        ,        inc  ,        
    //               ,        Thread ,            ,       synchronized
    return $this->synchronized(function () {
      $data = file_get_contents($this->file);
      $data = floatval($data);
      for ($i = 0; $i < 100000; $i++) {
        ++$data;
      }
      file_put_contents($this->file, $data);
      return $data;
    });
  }
}

class Task extends Thread
{
  private $name;
  private $file;

  public function __construct($name, $file)
  {
    $this->name = $name;
    $this->file = $file;
  }

  public function run()
  {
    $data = $this->file->inc();
    echo "task : {$this->name} data : {$data} 
"; } } $tasks = []; $file = new File('./test.log'); for ($i = 0; $i < 100; $i++) { $tasks[$i] = new Task($i, $file); $tasks[$i]->start(); } for ($i = 0; $i < 100; $i++) { $tasks[$i]->join(); }
결 과 는 다음 그림 에서 보 듯 이 물론 안전 을 위해 서 우 리 는 몇 번 더 운행 해 볼 수 있 습 니 다.다음은 제 가 25 번 운행 한 결과 입 니 다.

더 많은 PHP 관련 내용 에 관심 이 있 는 독자 들 은 본 사이트 의 주 제 를 볼 수 있다.
본 논문 에서 말 한 것 이 여러분 의 PHP 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기