"코 루틴"과 "스레드"의 차이점은 무엇입니까?


답변:


122

코 루틴은 순차적 처리의 한 형태입니다. 서브 루틴 AKA 프로 시저와 마찬가지로 AKA 기능과 마찬가지로 주어진 시간에 하나만 실행됩니다.

스레드는 (적어도 개념적으로) 동시 처리의 한 형태입니다. 주어진 시간에 여러 스레드가 실행될 수 있습니다. (전통적으로 단일 CPU, 단일 코어 시스템에서는 동시성을 OS의 도움을 받아 시뮬레이션했습니다. 요즘 많은 시스템이 다중 CPU 및 / 또는 다중 코어이기 때문에 스레드가 실제로 동시에 실행됩니다. "개념적으로"가 아니라).


188

첫 번째 읽기 : 동시성 대 병렬 처리-차이점은 무엇입니까?

동시성은 인터리브 된 실행을 제공하기 위해 작업을 분리하는 것입니다. 병렬 처리는 속도를 높이기 위해 여러 작업을 동시에 실행하는 것입니다. — https://github.com/servo/servo/wiki/Design

짧은 대답 : 스레드를 사용하면 운영 체제는 스케줄러에 따라 운영 스레드를 사전에 전환합니다. 이는 운영 체제 커널의 알고리즘입니다. 코 루틴을 사용하면 프로그래머와 프로그래밍 언어가 코 루틴을 전환 할시기를 결정합니다. 다시 말해, 태스크는 일반적으로 단일 스레드 내에서 설정 지점에서 기능을 일시 중지하고 다시 시작함으로써 협력 적으로 멀티 태스킹됩니다.

긴 대답 : 운영 체제에 의해 사전 예약 된 스레드와 달리 코 루틴 스위치는 협력 적이므로 스위치가 발생할 때 프로그래머 (및 프로그래밍 언어 및 런타임)가 제어합니다.

선점 형 스레드와 달리 코 루틴 스위치는 협력 적입니다 (스위치 발생시기를 프로그래머가 제어). 커널은 코 루틴 스위치에 관여하지 않습니다. — http://www.boost.org/doc/libs/1_55_0/libs/coroutine/doc/html/coroutine/overview.html

기본 스레드 를 지원하는 언어 는 스레드 (사용자 스레드)를 운영 체제 스레드 ( 커널 스레드 )에서 실행할 수 있습니다 . 모든 프로세스에는 최소한 하나의 커널 스레드가 있습니다. 커널 스레드는 소유 프로세스에서 메모리 공간을 해당 프로세스의 다른 모든 스레드와 공유한다는 점을 제외하고 프로세스와 유사합니다. 프로세스는 메모리, 파일 핸들, 소켓, 장치 핸들 등과 같이 할당 된 모든 리소스를 "소유"하며 이러한 리소스는 모두 커널 스레드간에 공유됩니다.

운영 체제 스케줄러는 단일 스레드 프로세서에서 특정 시간 동안 각 스레드를 실행하는 커널의 일부입니다. 스케줄러는 각 스레드에 시간 (타임 슬라이싱)을 할당하고 해당 시간 내에 스레드가 완료되지 않으면 스케줄러가이를 미리 비 웁니다 (인터럽트하고 다른 스레드로 전환). 각 스레드를 별도의 프로세서에 예약 할 수는 있지만 다중 프로세서 시스템에서 여러 스레드를 병렬로 실행할 수 있습니다.

단일 프로세서 시스템에서 스레드는 동시에 시간 분할되고 선점됩니다 (리눅스에서 기본 시간 조각은 100ms 임). 그러나 단일 코어 프로세서는 한 번에 하나만 실행할 수 있기 때문에 병렬로 동시에 실행할 수 없습니다.

코 루틴 및 / 또는 생성기 를 사용하여 협력 기능을 구현할 수 있습니다. 커널 스레드에서 실행되고 운영 체제에서 스케줄되는 대신, 생성 또는 완료 될 때까지 단일 스레드에서 실행되어 프로그래머가 결정한 다른 기능을 생성합니다. Python 및 ECMAScript 6과 같은 생성기가있는 언어를 사용하여 코 루틴을 작성할 수 있습니다. Async / await (C #, Python, ECMAscript 7, Rust에서 볼 수 있음)는 미래 / 약속을 산출하는 생성기 함수 위에 구축 된 추상화입니다.

일부 맥락에서, 코 루틴 은 스택 함수를 참조 할 수있는 반면 생성기 는 스택리스 함수를 참조 할 수 있습니다.

섬유 , 경량 실녹색 실은 코 루틴 또는 코 루틴 유사 물질의 다른 이름입니다. 때로는 프로그래밍 언어의 운영 체제 스레드와 비슷하게 보일 수 있지만 실제 스레드와 병렬로 실행되지 않고 코 루틴과 같이 작동합니다. (언어 나 구현에 따라이 개념들간에 더 구체적인 기술적 특성이나 차이점이있을 수 있습니다.)

예를 들어, Java에는 " 녹색 스레드 " 가있었습니다 . 기본 운영 체제의 커널 스레드 대신 JVM (Java Virtual Machine)에서 스케줄 된 스레드입니다. 네이티브 스레드가 필요하기 때문에 병렬로 실행되거나 여러 프로세서 / 코어를 활용하지 않았습니다! OS에 의해 예약되지 않았기 때문에 커널 스레드보다 코 루틴과 비슷했습니다. 녹색 스레드는 기본 스레드가 Java 1.2에 도입 될 때까지 Java가 사용한 것입니다.

스레드는 리소스를 소비합니다. JVM에서 각 스레드에는 일반적으로 1MB 크기의 자체 스택이 있습니다. 64k는 JVM에서 스레드 당 허용되는 최소 스택 공간입니다. 스레드 스택 크기는 JVM의 명령 행에서 구성 할 수 있습니다. 이름에도 불구하고 스레드마다 자체 스택이 필요한 각 스레드, 스레드 로컬 스토리지 (있는 경우) 및 스레드 스케줄링 / 컨텍스트 전환 / CPU 캐시 무효화 비용으로 인해 스레드는 사용 가능하지 않습니다. 이것이 코 루틴이 성능이 중요하고 동시성이 높은 응용 분야에서 인기를 얻은 이유의 일부입니다.

Mac OS는 프로세스에 약 2000 개의 스레드 만 할당 할 수 있으며 Linux는 스레드 당 8MB 스택을 할당하며 물리적 RAM에 맞는 스레드 수만 허용합니다.

따라서 스레드는 가장 큰 가중치 (메모리 사용 및 컨텍스트 전환 시간 측면에서), 코 루틴 및 마지막으로 생성기가 가장 가벼운 가중치입니다.


2
+1이지만이 답변은 일부 참조에서 도움이 될 수 있습니다.
kojiro

1
녹색 실은 코 루틴과는 다릅니다. 그렇지 않습니까? 섬유조차도 약간의 차이가 있습니다. programmers.stackexchange.com/questions/254140/…

113

약 7 년 늦었지만 여기에 대한 답변에는 스레드 대 스레드의 컨텍스트가 누락되었습니다. 왜 코 루틴이 최근에 많은 주목을 받고 있으며 스레드 와 비교하여 언제 사용 합니까?

우선 코 루틴이 동시에 ( 병렬로 연결 되지 않음) 실행 되는 경우 왜 스레드보다 스레드를 선호합니까?

대답은 코 루틴이 오버 헤드가 거의없이 매우 높은 수준의 동시성 을 제공 할 수 있다는 것입니다 . 일반적으로 스레드 환경에서는 실제로 시스템 스케줄러에 의해 이러한 스레드를 예약하는 오버 헤드 양이 낭비되기 전에 최대 30-50 개의 스레드가 있으므로 스레드가 실제로 유용한 작업을 수행하는 시간이 크게 줄어 듭니다 .

그렇다면 스레드를 사용하면 병렬 처리를 할 수 있지만 너무 많은 병렬 처리는 할 수 없지만 단일 스레드에서 실행되는 공동 루틴보다 여전히 낫지 않습니까? 반드시 그런 것은 아닙니다. 동시 루틴은 스케줄러 오버 헤드없이 동시성을 수행 할 수 있다는 점을 기억하십시오. 컨텍스트 전환 자체를 관리하기 만합니다.

예를 들어, 일부 작업을 수행하는 루틴이 있고 일정 시간 동안 (예 : 네트워크 요청) 차단할 작업을 수행하는 경우, 공동 루틴을 사용하면 시스템 스케줄러를 포함하지 않고 다른 루틴으로 즉시 전환 할 수 있습니다. 이 결정-예, 프로그래머 공동 루틴을 전환 할 수있는시기 지정 해야합니다 .

매우 적은 양의 작업을 수행하고 자발적으로 서로 전환하는 많은 루틴을 통해 스케줄러가 달성 할 수없는 효율성 수준에 도달했습니다. 수십 개의 스레드가 아닌 수천 개의 코 루틴을 함께 사용할 수 있습니다.

이제 루틴이 미리 결정된 지점간에 서로 전환되기 때문에 공유 데이터 구조에 대한 잠금피할 수 있습니다 (중요 섹션 중간에 다른 코 루틴으로 전환하도록 코드에 지시하지 않기 때문에).

또 다른 이점은 훨씬 적은 메모리 사용량입니다. 스레드 모델을 사용하면 각 스레드마다 고유 한 스택을 할당해야하므로 메모리 사용량은 스레드 수에 따라 선형 적으로 증가합니다. 코 루틴을 사용하면 루틴 수는 메모리 사용량과 직접적인 관계가 없습니다.

마지막으로, 코 루틴은 파이썬과 같은 일부 프로그래밍 언어에서 스레드가 병렬로 실행될 수 없기 때문에 많은 관심을 받고 있습니다. 코 루틴처럼 동시에 실행되지만 메모리가 적고 일정이없는 오버 헤드가 없습니다.


2
차단 작업이 발생할 때 코 루틴에서 다른 작업으로 전환하는 방법은 무엇입니까?
Narcisse Doudieu Siewe

다른 작업으로 전환하는 방법은 실제로 차단 작업을 비동기 적으로 수행하는 것입니다. 즉, 실제로 차단하는 작업은 사용하지 말아야하고 코 루틴 시스템에서 사용될 때 차단하지 않는 작업 만 사용해야합니다. 이 문제를 해결할 수있는 유일한 방법은 Windows의 UMS와 같이 커널에서 코 루틴을 지원하는 것입니다. 예를 들어 UMS "스레드"가 syscall에서 차단 될 때마다 스케줄러로 이동합니다.
retep998

@MartinKonecny ​​최근 C ++ Threads TS가 당신이 언급 한 접근법을 고수하고 있습니까?
Nikos

따라서 현대적인 프로그래밍 언어는 Coroutines / Fibers가 단일 CPU 코어를 효율적으로 활용하여 IO와 스레드와 같은 계산이 많이 필요없는 작업을 효율적으로 활용하여 많은 코어에서 CPU 집약적 인 작업을 병렬화하여 속도를 확보해야합니까?
Mahatma_Fatal_Error

19

한마디로 : 선점. 코 루틴은 저술가처럼 행동하여 서로 잘 연습 된 포인트를 서로에게 전합니다. 스레드 (실제 스레드)는 거의 모든 시점에서 중단 된 다음 나중에 다시 시작할 수 있습니다. 물론 이것은 모든 종류의 리소스 충돌 문제를 초래하므로 파이썬의 악명 높은 GIL-Global Interpreter Lock.

많은 스레드 구현은 실제로 코 루틴과 비슷합니다.


9

사용중인 언어에 따라 다릅니다. 예를 들어 루아에서 그들은 같은 것입니다 (코 루틴의 변수 유형은이라고합니다 thread).

일반적으로 코 루틴은 프로그래머가 어디에서 yield, 즉 다른 루틴을 제어 할 수 있는지 결정하는 자발적인 양보를 구현하지만 .

대신 스레드는 OS에 의해 자동으로 관리 (중지 및 시작)되며 멀티 코어 CPU에서 동시에 실행될 수도 있습니다.


0

12 년 후 논의가 늦었지만 코 루틴은 그 이름으로 설명을한다. 코 루틴은 Co와 루틴으로 분해 될 수 있습니다.

이러한 맥락에서 루틴은 일련의 동작 / 동작이며, 루틴을 실행 / 처리함으로써 동작 순서는 지정된 순서와 동일한 순서로 하나씩 실행됩니다.

공동 협력을 의미합니다. 공동 루틴은 다른 공동 루틴에게도 실행 기회를 제공하기 위해 실행을 기꺼이 일시 중단하도록 요청합니다. 따라서 공동 루틴은 CPU 리소스 공유 (의지)에 관한 것이므로 다른 사람들이 자신이 사용하는 것과 동일한 리소스를 사용할 수 있습니다.

반면에 스레드는 실행을 일시 중단 할 필요가 없습니다. 일시 중단은 스레드에 대해 완전히 투명하며 기본 하드웨어에 의해 스레드가 일시 중단됩니다. 또한 스레드가 알림을받지 않고 스레드가 계속 허용 될 때 상태가 변경되지 않고 저장되고 나중에 복원되므로 스레드에 대해 대부분 투명하게하는 방식으로 수행됩니다.

사실이 아닌 한 가지는, 공동 루틴을 동시에 실행할 수없고 경쟁 조건이 발생할 수 없다는 것입니다. 코 루틴이 실행되는 시스템에 따라 코 루틴을 쉽게 이미징 할 수 있습니다.

공동 루틴이 어떻게 일시 중단되는지는 중요하지 않습니다. Windows 3.1에서 int 03은 모든 프로그램으로 짜여져 있거나 (또는 ​​거기에 있어야 했음) C #에서는 수확량을 추가합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.