백엔드 개발 PHP 튜토리얼 PHP 프로그램_php 기술의 파일 잠금, 뮤텍스 잠금 및 읽기/쓰기 잠금 분석

PHP 프로그램_php 기술의 파일 잠금, 뮤텍스 잠금 및 읽기/쓰기 잠금 분석

May 16, 2016 pm 07:56 PM
php 뮤텍스 잠금 파일 잠금 읽기-쓰기 잠금 잠그다

파일 잠금
전체 이름은 책에서 언급한 권고 파일 잠금입니다. 이러한 유형의 잠금은 비교적 일반적입니다. 예를 들어, mysql과 php-fpm이 시작된 후에는 프로세스 ID를 기록하는 pid 파일이 있습니다.

이 잠금을 사용하면 프로세스가 반복적으로 실행되는 것을 방지할 수 있습니다. 예를 들어 crontab을 사용하면 1분마다 하나의 작업이 실행되도록 제한되지만 프로세스 잠금을 사용하여 해결하지 않으면 이 프로세스가 1분 이상 실행될 수 있습니다. 충돌이 발생하면 두 프로세스가 함께 실행되는 데 문제가 있습니다.

PID 파일 잠금을 사용하면 프로세스가 중지 또는 다시 시작 신호를 자체적으로 보내는 것이 편리하다는 또 다른 이점이 있습니다. 예를 들어 php-fpm을 다시 시작하는 명령은

입니다.

kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
USR2 신호를 pid 파일에 기록된 프로세스로 보냅니다. 신호는 프로세스 통신에 속하며 다른 장에서 설명합니다.

PHP의 인터페이스는 매우 다양하며 문서는 비교적 자세합니다. 먼저 정의를 살펴보겠습니다. bool Flock (resource $handle , int $Operation [, int &$wouldblock ] ).

  • $handle은 일반적으로 fopen()에 의해 생성되는 리소스인 파일 시스템 포인터입니다. 이는 Flock을 사용하려면 파일을 열어야 함을 의미합니다.
  • $Operation은 작업 유형입니다.
  • &$wouldblock 잠금이 차단되면 이 변수는 1로 설정됩니다.

이 함수는 기본적으로 차단된다는 점에 유의해야 합니다. 비차단을 원할 경우 비트마스크 LOCK_NB를 작업에 추가하여 테스트할 수 있습니다.

$pid_file = "/tmp/process.pid";
$pid = posix_getpid();
$fp = fopen($pid_file, 'w+');
if(flock($fp, LOCK_EX | LOCK_NB)){
  echo "got the lock \n";
  ftruncate($fp, 0);   // truncate file
  fwrite($fp, $pid);
  fflush($fp);      // flush output before releasing the lock
  sleep(300); // long running process
  flock($fp, LOCK_UN);  // 释放锁定
} else {
  echo "Cannot get pid lock. The process is already up \n";
}
fclose($fp);
로그인 후 복사

process.php로 저장하고 php process.php &를 실행한 다음 php process.php를 다시 실행하면 오류 메시지가 표시됩니다. Flock에는 공유 잠금 LOCK_SH도 있습니다.

뮤텍스 잠금 및 읽기/쓰기 잠금
동기화 모듈의 뮤텍스:
뮤텍스는 상호배제, 상호배제의 합성어입니다. pecl을 사용하여 동기화 모듈을 설치하고 pecl install sync를 설치합니다. 문서의 SyncMutex에는 잠금 및 잠금 해제 두 가지 메서드만 있습니다. 바로 코드 테스트로 이동하겠습니다. 저는 IDE에서 작성하지 않았으므로 cs가 매우 추악합니다. 무시하십시오.

$mutex = new SyncMutex("UniqueName");

for($i=0; $i<2; $i++){
  $pid = pcntl_fork();
  if($pid <0){
    die("fork failed");
  }elseif ($pid>0){
    echo "parent process \n";
  }else{
    echo "child process {$i} is born. \n";
    obtainLock($mutex, $i);
  }
}

while (pcntl_waitpid(0, $status) != -1) { 
  $status = pcntl_wexitstatus($status); 
  echo "Child $status completed\n"; 
}

function obtainLock ($mutex, $i){
  echo "process {$i} is getting the mutex \n";
  $res = $mutex->lock(200);
  sleep(1);
  if (!$res){
    echo "process {$i} unable to lock mutex. \n";
  }else{
    echo "process {$i} successfully got the mutex \n";
    $mutex->unlock();
  }
  exit();
}

로그인 후 복사

mutex.php로 저장하고 php mutex.php를 실행하면 출력은 다음과 같습니다

parent process 
parent process 
child process 1 is born. 
process 1 is getting the mutex 
child process 0 is born. 
process 0 is getting the mutex 
process 1 successfully got the mutex 
Child 0 completed
process 0 unable to lock mutex. 
Child 0 completed
로그인 후 복사

여기서 하위 프로세스 0과 1이 반드시 앞에 있을 필요는 없습니다. 그러나 자물쇠를 얻지 못하는 사람은 항상 있습니다. 여기서 SyncMutex::lock(int $millisecond)의 매개변수는 차단 기간을 나타내는 밀리초이고, -1은 무한 차단을 의미합니다.

동기화 모듈의 읽기-쓰기 잠금:
SyncReaderWriter의 메소드는 readlock, readunlock, writelock, writeunlock과 유사하며, 작성된 테스트 코드가 없으며 Mutex 코드와 일치해야 하며 잠금만 교체하면 됩니다.

동기화 모듈의 이벤트:
golang의 Cond와 같은 느낌이 들며, wait()가 차단되고, fire()가 Event에 의해 차단된 프로세스를 깨웁니다. Cond를 소개하는 좋은 기사가 있습니다. Cond는 고정된 잠금 사용법임을 알 수 있습니다. SyncEvent도 마찬가지입니다.
PHP 문서의 예에서는 fire() 메소드가 웹 애플리케이션에서 사용되는 것으로 보입니다.

테스트 코드

for($i=0; $i<3; $i++){
  $pid = pcntl_fork();
  if($pid <0){
    die("fork failed");
  }elseif ($pid>0){
    //echo "parent process \n";
  }else{
    echo "child process {$i} is born. \n";
    switch ($i) {
    case 0:
      wait();
      break;
    case 1:
      wait();
      break;
    case 2:
      sleep(1);
      fire();
      break;
    }
  }
}

while (pcntl_waitpid(0, $status) != -1) { 
  $status = pcntl_wexitstatus($status); 
  echo "Child $status completed\n"; 
}

function wait(){
  $event = new SyncEvent("UniqueName");
  echo "before waiting. \n";
  $event->wait();
  echo "after waiting. \n";
  exit();
}

function fire(){
  $event = new SyncEvent("UniqueName");
  $event->fire();
  exit();
}

로그인 후 복사

여기에는 의도적으로 One fire()를 작성하여 프로그램이 차단됩니다. 이는 fire()가 한 번에 하나의 프로세스만 깨운다는 것을 증명합니다.

pthread 모듈
뮤텍스 잠금 및 잠금 해제:

기능:

pthread_mutex_lock (mutex) 
pthread_mutex_trylock (mutex) 
pthread_mutex_unlock (mutex) 
로그인 후 복사

사용법:

스레드는 pthread_mutex_lock() 함수를 사용하여 지정된 뮤텍스 변수를 잠급니다. 다른 스레드가 뮤텍스를 이미 잠근 경우 이 호출은 뮤텍스가 잠금 해제될 때까지 스레드를 차단합니다.
pthread_mutex_trylock()은 뮤텍스를 잠그려고 시도합니다. 그러나 뮤텍스가 이미 잠겨 있으면 루틴은 "busy" 오류 코드와 함께 즉시 반환됩니다. 이 루틴은 pthread_mutex_trylock()에서 유용할 수 있습니다.

뮤텍스를 잠그려고 시도합니다. 그러나 뮤텍스가 이미 잠긴 경우 프로그램은 즉시 사용 중 오류 값을 반환합니다. 이 기능은 우선순위 변경 시 교착상태를 방지하는 데 유용합니다. 스레드는 pthread_mutex_unlock()을 사용하여 자신이 차지하는 뮤텍스를 잠금 해제할 수 있습니다. 한 스레드가 보호된 데이터의 사용을 완료하고 다른 스레드가 보호된 데이터에 대해 작업하기 위해 뮤텍스를 얻으려고 할 때 이 함수를 호출할 수 있습니다. 다음과 같은 상황이 발생하면 오류가 발생합니다.

  • 뮤텍스가 잠금 해제되었습니다
  • 다른 스레드가 뮤텍스를 차지하고 있습니다

뮤텍스에 대해 "마법적인" 것은 없습니다. 사실 이는 참여 스레드의 "신사 합의"입니다. 코드를 작성할 때 뮤텍스를 올바르게 잠그고 잠금 해제해야 합니다.

Q: 동일한 잠긴 뮤텍스를 기다리는 스레드가 여러 개 있습니다. 뮤텍스가 잠금 해제되면 가장 먼저 뮤텍스를 잠그는 스레드는 무엇입니까?
A: 스레드가 우선 순위 예약 메커니즘을 사용하지 않는 한 시스템 스케줄러에 의해 스레드가 할당되며 뮤텍스를 먼저 잠그는 스레드는 무작위입니다.

#include<stdlib.h> 
#include<stdio.h> 
#include<unistd.h> 
#include<pthread.h> 

typedef struct ct_sum 
{ 
  int sum; 
  pthread_mutex_t lock; 
}ct_sum; 

void * add1(void *cnt) 
{    
  pthread_mutex_lock(&(((ct_sum*)cnt)->lock)); 
  for(int i=0; i < 50; i++) 
  {
    (*(ct_sum*)cnt).sum += i;   
  } 
  pthread_mutex_unlock(&(((ct_sum*)cnt)->lock)); 
  pthread_exit(NULL); 
  return 0; 
} 
void * add2(void *cnt) 
{    
  pthread_mutex_lock(&(((ct_sum*)cnt)->lock)); 
  for(int i=50; i<101; i++) 
  {  
     (*(ct_sum*)cnt).sum += i;  
  } 
  pthread_mutex_unlock(&(((ct_sum*)cnt)->lock)); 
  pthread_exit(NULL); 
  return 0; 
} 
 
int main(void) 
{
  pthread_t ptid1, ptid2; 
  ct_sum cnt; 
  pthread_mutex_init(&(cnt.lock), NULL); 
  cnt.sum=0; 
 
  pthread_create(&ptid1, NULL, add1, &cnt); 
  pthread_create(&ptid2, NULL, add2, &cnt); 
  
  pthread_join(ptid1,NULL); 
  pthread_join(ptid2,NULL);

  printf("sum %d\n", cnt.sum);
  pthread_mutex_destroy(&(cnt.lock)); 

  return 0; 
}

로그인 후 복사

信号量
sync模块中的信号量:
SyncSemaphore文档中显示,它和Mutex的不同之处,在于Semaphore一次可以被多个进程(或线程)得到,而Mutex一次只能被一个得到。所以在SyncSemaphore的构造函数中,有一个参数指定信号量可以被多少进程得到。
public SyncSemaphore::__construct ([ string $name [, integer $initialval [, bool $autounlock ]]] ) 就是这个$initialval (initial value)

$lock = new SyncSemaphore("UniqueName", 2);

for($i=0; $i<2; $i++){
  $pid = pcntl_fork();
  if($pid <0){
    die("fork failed");
  }elseif ($pid>0){
    echo "parent process \n";
  }else{
    echo "child process {$i} is born. \n";
    obtainLock($lock, $i);
  }
}

while (pcntl_waitpid(0, $status) != -1) { 
  $status = pcntl_wexitstatus($status); 
  echo "Child $status completed\n"; 
}

function obtainLock ($lock, $i){
  echo "process {$i} is getting the lock \n";
  $res = $lock->lock(200);
  sleep(1);
  if (!$res){
    echo "process {$i} unable to lock lock. \n";
  }else{
    echo "process {$i} successfully got the lock \n";
    $lock->unlock();
  }
  exit();
}

로그인 후 복사

这时候两个进程都能得到锁。

  • sysvsem模块中的信号量
  • sem_get 创建信号量
  • sem_remove 删除信号量(一般不用)
  • sem_acquire 请求得到信号量
  • sem_release 释放信号量。和 sem_acquire 成对使用。
$key = ftok('/tmp', 'c');

$sem = sem_get($key);

for($i=0; $i<2; $i++){
  $pid = pcntl_fork();
  if($pid <0){
    die("fork failed");
  }elseif ($pid>0){
    //echo "parent process \n";
  }else{
    echo "child process {$i} is born. \n";
    obtainLock($sem, $i);
  }
}

while (pcntl_waitpid(0, $status) != -1) { 
  $status = pcntl_wexitstatus($status); 
  echo "Child $status completed\n"; 
}
sem_remove($sem); // finally remove the sem

function obtainLock ($sem, $i){
  echo "process {$i} is getting the sem \n";
  $res = sem_acquire($sem, true);
  sleep(1);
  if (!$res){
    echo "process {$i} unable to get sem. \n";
  }else{
    echo "process {$i} successfully got the sem \n";
    sem_release($sem);
  }
  exit();
}

로그인 후 복사

这里有一个问题,sem_acquire()第二个参数$nowait默认为false,阻塞。我设为了true,如果得到锁失败,那么后面的sem_release会报警告 PHP Warning: sem_release(): SysV semaphore 4 (key 0x63000081) is not currently acquired in /home/jason/sysvsem.php on line 33, 所以这里的release操作必须放在得到锁的情况下执行,前面的几个例子中没有这个问题,没得到锁执行release也不会报错。当然最好还是成对出现,确保得到锁的情况下再release。
此外,ftok这个方法的参数有必要说明下,第一个 必须是existing, accessable的文件, 一般使用项目中的文件,第二个是单字符字符串。返回一个int。

输出为

parent process 
parent process 
child process 1 is born. 
process 1 is getting the mutex 
child process 0 is born. 
process 0 is getting the mutex 
process 1 successfully got the mutex 
Child 0 completed
process 0 unable to lock mutex. 
Child 0 completed

로그인 후 복사

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

CakePHP 프로젝트 구성 CakePHP 프로젝트 구성 Sep 10, 2024 pm 05:25 PM

이번 장에서는 CakePHP의 환경 변수, 일반 구성, 데이터베이스 구성, 이메일 구성에 대해 알아봅니다.

Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Dec 24, 2024 pm 04:42 PM

PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP 날짜 및 시간 CakePHP 날짜 및 시간 Sep 10, 2024 pm 05:27 PM

cakephp4에서 날짜와 시간을 다루기 위해 사용 가능한 FrozenTime 클래스를 활용하겠습니다.

CakePHP 파일 업로드 CakePHP 파일 업로드 Sep 10, 2024 pm 05:27 PM

파일 업로드 작업을 위해 양식 도우미를 사용할 것입니다. 다음은 파일 업로드의 예입니다.

CakePHP 라우팅 CakePHP 라우팅 Sep 10, 2024 pm 05:25 PM

이번 장에서는 라우팅과 관련된 다음과 같은 주제를 학습하겠습니다.

CakePHP 토론 CakePHP 토론 Sep 10, 2024 pm 05:28 PM

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

CakePHP 유효성 검사기 만들기 CakePHP 유효성 검사기 만들기 Sep 10, 2024 pm 05:26 PM

컨트롤러에 다음 두 줄을 추가하면 유효성 검사기를 만들 수 있습니다.

PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 Dec 20, 2024 am 11:31 AM

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

See all articles