>  기사  >  백엔드 개발  >  PHP 코루틴에 대한 자세한 설명(예제 포함)

PHP 코루틴에 대한 자세한 설명(예제 포함)

不言
不言원래의
2018-09-20 17:41:325110검색

이 글은 PHP 코루틴에 대한 자세한 설명을 제공합니다(예제 포함). 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

멀티 태스킹(병렬 및 동시성)

코루틴에 대해 이야기하기 전에 다중 프로세스, 다중 스레드, 병렬성 및 동시성에 대해 이야기해 보겠습니다.

단일 코어 프로세서의 경우 다중 프로세스 멀티태스킹의 원리는 운영 체제가 매번 특정 CPU 시간 조각을 작업에 할당한 후 중단하고 다음 작업이 특정 시간 조각 동안 실행되도록 한 다음 중단하고 계속해서 실행하세요.

실행 작업 전환이 매우 빠르기 때문에 외부 사용자에게 주어지는 인상은 여러 작업이 동시에 실행된다는 것입니다.

다중 프로세스의 스케줄링은 운영 체제에 의해 구현됩니다. 즉, 프로세스 스케줄링은 외부 스케줄러implemented<code>进程的调度是由外层调度器抢占式实现的

而协程要求当前正在运行的任务自动把控制权回传给调度器,这样就可以继续运行其他任务。这与抢占式的多任务正好相反, 抢占多任务的调度器可以强制中断正在运行的任务, 不管它自己有没有意愿。如果仅依靠程序自动交出控制的话,那么一些恶意程序将会很容易占用全部 CPU 时间而不与其他任务共享。

协程的调度是由协程自身主动让出控制权到外层调度器实现的

回到刚才生成器实现 xrange 函数的例子,整个执行过程的交替可以用下图来表示:

协程可以理解为纯用户态的线程,通过协作而不是抢占来进行任务切换。

相对于进程或者线程,协程所有的操作都可以在用户态而非操作系统内核态完成,创建和切换的消耗非常低。

简单的说协程 就是提供一种方法来中断当前任务的执行,保存当前的局部变量,下次再过来又可以恢复当前局部变量继续执行。

我们可以把大任务拆分成多个小任务轮流执行,如果有某个小任务在等待系统 IO,就跳过它,执行下一个小任务,这样往复调度,实现了 IO 操作和 CPU 计算的并行执行,总体上就提升了任务的执行效率,这也便是协程的意义

多线程
在单核下,多线程必定是并发的;
不过现在的统一进程的多线程是可以运行在多核CPU下,所以可以是并行的

并发(Concurrency)

是指能处理多个同时性活动的能力,并发事件之间不一定要同一时刻发生。

并行(Parallesim)

是指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行。
多个操作可以在重叠的时间段内进行。

并行和并发区别

并发指的是程序的结构,并行指的是程序运行时的状态
并行一定是并发的,并行并发设计的一种
单线程永远无法达到并行状态

协程

协程的支持是在生成器
코루틴에서는 현재 실행 중인 작업이 자동으로 제어권을 스케줄러에 다시 전달해야 다른 작업이 계속 실행될 수 있습니다. 이는 선점형 멀티태스킹의 정반대입니다. 선점형 멀티태스킹의 스케줄러는 자체 의도와 관계없이 실행 중인 작업을 강제로 중단할 수 있습니다. 프로그램이 자동으로 제어권을 넘겨준다면 일부 악성 프로그램이 다른 작업과 공유하지 않고 CPU 시간을 모두 차지하기 쉬울 것입니다.

코루틴의 스케줄링은 외부 스케줄러에 대한 제어권을 포기하는 코루틴 자체에 의해 적극적으로 구현됩니다.

xrange 함수를 구현하는 생성기의 예로 돌아가면 전체 실행 프로세스는 다음과 같습니다. 다음 그림은 다음 그림을 보여줍니다.

코루틴은 선점 대신 협업을 통해 작업 전환을 수행하는 순수 사용자 모드 스레드로 이해될 수 있습니다.

프로세스나 스레드에 비해 코루틴의 모든 작업은 운영체제 커널 모드가 아닌 사용자 모드에서 완료될 수 있으며 생성 및 전환 비용이 매우 저렴합니다.

간단히 말하면, 코루틴은 현재 작업의 실행을 중단하고, 현재 지역 변수를 저장하고, 다음 번 실행을 계속하기 위해 현재 지역 변수를 복원하는 방법을 제공합니다.

대규모 작업을 여러 개의 작은 작업으로 분할하여 차례로 실행할 수 있습니다. 시스템 IO를 기다리는 작은 작업이 있으면 이를 건너뛰고 다음 작은 작업을 실행할 수 있습니다. 이 왕복 스케줄링은 IO 작업 및 CPU 계산을 실현합니다. 병렬 실행은 일반적으로 작업의 실행 효율성을 향상시킵니다. 이것이 바로 코루틴의 의미입니다


멀티 스레딩

싱글 코어에서는 멀티 스레딩이 동시 실행되어야 합니다.

그러나 현재 통합 프로세스의 멀티 스레딩은 가능합니다.

🎜동시성🎜🎜은 동시 이벤트가 반드시 동시에 발생할 필요는 없습니다. 🎜🎜Parallelsim🎜🎜은 동시에 발생하는 두 개의 동시 이벤트를 말하며 동시성이라는 의미를 갖지만 동시성이 반드시 병렬인 ​​것은 아닙니다. 🎜겹치는 기간 내에 여러 작업을 수행할 수 있습니다. 🎜🎜병렬성과 동시성의 차이점🎜🎜동시성은 프로그램의 구조를 나타내고, 병렬은 프로그램이 실행 중일 때의 상태를 나타냅니다.🎜병렬 는 동시적이어야 하며, 병렬동시성 설계 유형입니다🎜단일 스레드는 결코 병렬 상태에 도달할 수 없습니다🎜🎜코루틴🎜 🎜코루틴 지원은 Generator를 기반으로 제너레이터로 데이터를 다시 보내는 기능(호출자가 호출된 제너레이터 함수로 데이터를 보내는 기능)이 추가되었습니다. 호출자에 대한 생성기 통신은 둘 사이의 양방향 통신으로 변경됩니다. 🎜 이미 이전 기사에서 전송 방법에 대해 설명했습니다. 코루틴을 이해해 보겠습니다. 🎜🎜 동기 코드 🎜🎜 비동기 실행 코드가 포함되기 전에 code 이렇습니다🎜
function printNum($max, $caller)
{
    for ($i=0; $i<$max; $i++ ) {
        echo "调度者:" . $caller . "  打印:" . $i . PHP_EOL;
    }
}

printNum(3, "caller1");
printNum(3, "caller2");

# output
调度者:caller1  打印:0
调度者:caller1  打印:1
调度者:caller1  打印:2
调度者:caller2  打印:0
调度者:caller2  打印:1
调度者:caller2  打印:2
🎜코루틴 사용 후 개선된 코드🎜🎜첫 번째 초안, 생성기 실행 수동 조정🎜
# 本代码手动调整了进程执行代码的顺序,当然本代码实现不用协程也可以,只是利用本流程说明协程作用
# 生成器给了我们函数中断,协程[生成器send]给了我们重新唤起生成器函数的能力
function printNumWithGen($max)
{
    for ($i=0; $i<$max; $i++ ) {
        $res = yield $i;
        echo $res;
    }
}

$gen1 = printNumWithGen(3);
$gen2 = printNumWithGen(3);

// 手动执行caller1 再 caller2
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);

// 手动执行caller1 再 caller2
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);

// 手动执行caller2 再 caller1
$gen2->send("调度者: caller2 打印:" . $gen2->current() . PHP_EOL);
$gen1->send("调度者: caller1 打印:" . $gen1->current() . PHP_EOL);

# output
调度者: caller1 打印:0
调度者: caller2 打印:0
调度者: caller1 打印:1
调度者: caller2 打印:1
调度者: caller2 打印:2
调度者: caller1 打印:2
🎜요약🎜🎜위 사례를 통해 모두가 코루틴 설계의 의미와 코루틴 사용 방법을 이해할 수 있을 것입니다🎜그럼 계속해서 Automate 코루틴을 위한 자동 스케줄러(공동 자동 실행기), 수동으로 중단하고 재개할 필요가 없습니다🎜🎜🎜

위 내용은 PHP 코루틴에 대한 자세한 설명(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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