>  기사  >  백엔드 개발  >  PHP 프로세스 통신의 세마포어를 간략하게 이해합니다.

PHP 프로세스 통신의 세마포어를 간략하게 이해합니다.

WBOY
WBOY앞으로
2022-09-02 16:57:222111검색

(권장 튜토리얼: PHP 비디오 튜토리얼)

공통 프로세스 통신 방법

일부 이론적 근거

  • 핵심 리소스: 한 번에 하나의 프로세스만 액세스할 수 있는 리소스입니다.
  • Critical 섹션: 중요한 리소스에 액세스하는 각 프로세스의 코드 섹션을 크리티컬 섹션이라고 합니다

소위 크리티컬 섹션(Critical 섹션이라고도 함)은 공유 데이터에 액세스하고 운영하는 코드 세그먼트입니다.

프로세스 상호 배제: 두 개 이상의 프로세스가 동일한 공유 변수 집합의 중요 영역에 동시에 들어갈 수 없습니다. 즉, 한 프로세스가 중요한 리소스에 액세스하고 다른 프로세스는 액세스하기 전에 기다려야 합니다.

프로세스 동기화: 여러 프로세스 간의 실행 순서를 결정하고 데이터 경쟁 문제를 피하는 방법, 즉 여러 프로세스가 함께 잘 실행되도록 하는 방법을 주로 연구합니다.

소위 동기화는 동시 프로세스/스레드가 일부에 있다는 것을 의미합니다. 포인트는 서로를 기다리고 메시지를 교환해야 할 수 있습니다. 이러한 상호 제한된 대기 및 정보 교환을 프로세스/스레드 동기화라고 합니다.

삶의 동기화의 예를 들자면, 배가 고프고 먹고 싶어 엄마에게 일찍 요리하라고 합니다. 이 말을 듣고 엄마는 요리를 시작하지만 엄마가 요리를 마치기 전에 막아서 기다려야 합니다. 식사가 끝나면 자연스럽게 알림을 받고 식사를 진행할 수 있습니다.

동기화와 상호 배제는 두 가지 다른 개념입니다.

동기화는 "작업 A는 작업 B보다 먼저 실행되어야 합니다", "작업 C는 작업 A와 작업 B가 모두 완료된 후에 실행되어야 합니다" 등과 같습니다.

상호 배제는 "작업 A와 작업 B를 동시에 실행할 수 없습니다"와 같습니다.

system V 세마포

세마포 사용: 주로 공용 리소스 개체에 대한 다중 프로세스 또는 다중 스레드 액세스 제어에 사용됩니다. 잠금과 유사하게 다중 프로세스(다중 스레드 동기화) 문제를 해결하고 액세스하기 전에 잠금을 획득하고(획득되지 않은 경우 대기) 액세스 후 잠금을 해제하는 데 사용됩니다.

다중 프로세스/다중 스레드는 일반적으로 동시에 실행됩니다. 공용 리소스에 대한 액세스가 동기화되지 않으면 데이터 손상이 발생하기 쉽습니다.

세마포어는 실제로 프로세스 간의 상호 배제 및 동기화를 달성하는 데 사용되는 정수 카운터입니다. 프로세스 간 통신을 위한 데이터 캐싱.

세마포어는 리소스 수를 나타냅니다. 세마포어를 제어하는 ​​두 가지 원자 연산이 있습니다.

하나는 P 연산입니다. 이 연산은 세마포어

다른 하나는 V 작업입니다. 이 작업은 추가 후 세마포 0이면 현재 차단된 프로세스가 없음을 나타냅니다. 공유 리소스에 들어가기 전에

P 작업이 사용되고 공유 리소스를 떠난 후에 V 작업이 사용됩니다. 쌍으로.

예를 들어, 2개의 자원의 세마포어는 2개의 열차 선로와 동일합니다. PV 연산 프로세스는 다음과 같습니다.

A 열차가 선로에 진입하며, 이는 세마포어의 P 연산과 동일하며, 자원은 는 -1이므로 선로가 하나 남습니다

그리고 또 다른 열차가 다른 선로를 점유하는데, 이는 P 연산, 자원 -1

이때 선로가 없기 때문에 신호등이 빨간색으로 변합니다. 세 번째 열차는 기다려야 합니다

첫 번째 열차는 선로를 떠나며 이는 V 운영과 동일합니다. 이때 선로 자원은 1이고 신호등이 녹색으로 변합니다

세 번째 열차가 찾습니다. 신호등이 녹색으로 바뀌어서 선로에 진입하고, 선로 자원이 0이 되어 신호등이 빨간색으로 바뀐다는 것

이 열차 선로 시스템에서 선로는 공공 자원이고, 각 열차는 실과 같으며, 신호등은 세마포어 역할을 합니다. 세마포어는 잠금의 상호 배제 동작을 구현할 수 있으며 프로세스/스레드 동기화도 구현할 수 있습니다

세마포 유형

1) 바이너리 세마포어(바이너리 세마포라고도 함)

이 때 세마포어의 초기 값은 0과 1만 있을 수 있다. (바이너리 세마포어는 뮤텍스 잠금 연산을 구현할 수 있습니다.)

2) 일반/카운팅 세마포

이때 세마포어의 초기값은 음수가 아닌 임의의 숫자가 될 수 있습니다. 분명히 이진 세마포어가 포함되어 있습니다. 위에서 언급한 기차 트랙 예제는 카운팅 세마포어를 사용하여 구현할 수 있습니다. 일반적으로 카운팅 세마포어와 잠금의 차이점은 여러 스레드/프로세스(스레드 수는 카운팅 세마포어의 초기 값에 의해 정의됨)를 허용한다는 것입니다. 공용 리소스를 동시에 운영

일반적으로 여러 프로세스를 개발할 때 세마포어만 사용해야 하는 경우가 있습니다. PHP에서는 공용 리소스에서 여러 프로세스가 작동하더라도 세마포어를 사용하는 경우가 거의 없습니다. 무리 파일 잠금은 주로 상호 배제 작업에 사용됩니다

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이어야 하지만 안타깝게도 그렇지 않습니다. 따라서 위 스크립트를 실행해 보겠습니다. $x 最后写入文件的值应该是2000,但很不幸,并不是如此,我们对上面的脚本执行一下:

运行了1000次,发现出现了变量$x值结果是 1000 的有8次,虽然发生错误的概率比较小,但是在计算机里是不能容忍的。

为什么会出现这种情况,我们知道单核cpu系统里为了实现多个程序同时运行的假象,操作系统通常都采用时间片调度,一个进程时间片用完就切换下一个进程运行,加上我们的高级语言不是每一行代码都是原子性的,比如x = (int)file_get_contents($file)

1000번 실행해 보니 변수 $x의 값이 8번 나오고 결과는 1000이 나왔습니다. 오류가 발생할 가능성은 상대적으로 적으며 컴퓨터에서는 허용되지 않습니다.

이런 일이 발생하는 이유는 무엇입니까? 단일 코어 CPU 시스템에서 여러 프로그램이 동시에 실행되는 환상을 달성하기 위해 운영 체제는 일반적으로 한 프로세스의 타임 슬라이스를 사용할 때 타임 슬라이스 스케줄링을 사용합니다. 또한 고급 언어의 모든 코드 줄이 원자적이지는 않습니다. 예를 들어 x = (int)file_get_contents($file) code> 이 코드 줄은 우리에게는 분할될 수 없지만 컴파일러에 의해 어셈블리 코드(기계 명령어)로 컴파일되므로 여러 명령어로 구현될 수 있으므로 명령어가 절반만 실행될 경우 문제가 발생합니다. 프로세스에서 할당한 슬라이스가 다른 프로세스에 의해 사용되거나 중단되면 데이터 손상이 발생하여 최종 계산 결과에 오류가 발생할 수 있습니다

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 操作 释放信号量
세마포어를 추가한 후 반드시 2000이 100% 보장되며 다른 값은 절대 나타나지 않습니다.

🎜(추천 튜토리얼: 🎜PHP 비디오 튜토리얼🎜)🎜

위 내용은 PHP 프로세스 통신의 세마포어를 간략하게 이해합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 jb51.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제