답변:
코 루틴은 언뜻 보면 스레드처럼 작동하는 것처럼 보이지만 실제로는 멀티 스레딩을 사용하지 않습니다. 그들은 때까지 순차적으로 실행됩니다 yield
. 엔진은 자신의 메인 루프의 일환으로 (지적 정확히의 종류에 따라 무엇을 전혀 굴복 코 루틴 확인합니다 yield
, 자세한 내용은이 그림을 확인을 ) 그들에게 그들의 다음까지 잇달아 계속 yield
하고 메인 루프를 진행합니다.
이 기술은 실제 멀티 스레딩 문제로 인한 두통없이 코 루틴을 사용할 수 있다는 이점이 있습니다. 컨텍스트 스위치로 인한 교착 상태, 경쟁 조건 또는 성능 문제가 발생하지 않으며 제대로 디버깅 할 수 있으며 스레드 안전 데이터 컨테이너를 사용할 필요가 없습니다. 코 루틴이 실행될 때 Unity 엔진이 제어 상태에 있기 때문입니다. 대부분의 Unity 기능을 사용하는 것이 안전합니다.
반면 스레드를 사용하면 현재 Unity 메인 루프의 상태에 대해 전혀 알지 못합니다 (사실 더 이상 전혀 실행되지 않을 수 있음). 따라서 스레드는 해당 작업을 수행하지 않아야 할 작업을 한 번에 수행하여 많은 혼란을 유발할 수 있습니다. 서브 스레드에서 기본 Unity 기능을 만지지 마십시오 . 서브 스레드와 메인 스레드간에 통신해야하는 경우 스레드가 thread-safe (!) 컨테이너 객체에 쓰도록하고 MonoBehaviour가 일반적인 Unity 이벤트 함수 동안 해당 정보를 읽도록합니다.
"실제"멀티 스레딩을 수행하지 않는 단점은 코 루틴을 사용하여 여러 CPU 코어에서 CPU 강렬 계산을 병렬화 할 수 없다는 것입니다. 그러나이를 사용하여 계산을 여러 업데이트로 분할 할 수 있습니다. 따라서 1 초 동안 게임을 정지시키는 대신 몇 초에 걸쳐 평균 프레임 속도가 낮아집니다. 그러나이 경우 귀하는yield
Unity가 업데이트를 실행하도록 할 때마다 코 루틴에 있습니다.
결론:
코 루틴은 컴퓨터 과학에서 "협업 멀티 태스킹"이라고합니다. 여러 개의 서로 다른 실행 스트림이 서로 협력하여 인터리브하는 방법입니다. 협력적인 멀티 태스킹에서 한 실행 스트림은 CPU가에 도달 할 때까지 논란의 여지가없는 소유권을 갖습니다 yield
. 이때 Unity (또는 사용중인 프레임 워크)에는 다른 실행 스트림으로 전환 할 수있는 옵션이 있습니다. 그런 다음 CPU에 대한 확실한 소유권을 갖습니다.yield
.
스레드는 "선점 형 멀티 태스킹"이라고합니다. 스레드를 사용하는 경우 프레임 워크는 언제든지 스레드를 중간에 중지하고 다른 스레드로 전환 할 수 . 당신이 어디에 있든 상관 없습니다. 경우에 따라 변수를 메모리에 쓰는 과정에서 도중에 멈출 수도 있습니다!
각각의 장단점이 있습니다. 코 루틴의 단점은 아마도 가장 이해하기 쉬울 것입니다. 먼저 코 루틴은 모두 단일 코어에서 실행됩니다. 쿼드 코어 CPU가있는 경우 코 루틴은 4 개의 코어 중 하나만 사용합니다. 이것은 일을 단순화하지만 경우에 따라 성능 문제가 될 수 있습니다. 두 번째 단점은 모든 코 루틴이 단순히 거부함으로써 전체 프로그램을 중지시킬 수 있다는 점을 알아야한다는 것 yield
입니다. 이것은 몇 년 전 Mac OS9의 문제였습니다. OS9은 전체 컴퓨터에서 협업 멀티 태스킹 만 지원했습니다. 프로그램 중 하나가 중단되면 컴퓨터가 너무 심하게 정지되어 OS가 오류 메시지의 텍스트를 렌더링하여 어떤 일이 있었는지 알 수 없습니다!
코 루틴의 장점은 상대적으로 이해하기 쉽다는 것입니다. 당신이 가진 오류는 훨씬 더 예측 가능합니다. 또한 일반적으로 더 적은 리소스를 요구하는데, 이는 수만 개의 코 루틴 또는 스레드로 올라갈 때 도움이 될 수 있습니다. 솔직한 문은 실을 제대로 연구하지 않았다면 코 루틴을 고수하면 옳다는 의견에 언급했습니다. 코 루틴은 작업하기가 훨씬 간단합니다.
실은 완전히 다른 짐승입니다. 다른 스레드가 방해 할 가능성에 대비하여 항상 경계해야합니다. 언제든지 해야합니다.데이터가 엉망입니다. 스레딩 라이브러리는 OS를 다른 스레드 중 하나를 실행하는 것이 안전하고 안전하지 않은 경우 OS에 알리는 데 도움이되는 뮤텍스 및 조건 변수와 같이이를 지원하는 강력한 도구 모음을 제공합니다. 이러한 도구를 잘 사용하는 방법에 대한 전 과정이 있습니다. 발생하는 유명한 문제 중 하나는 "데드락 (deadlock)"인데, 이는 두 스레드가 둘 다 다른 리소스를 확보하기 위해 "고정"될 때입니다. Unity에서 매우 중요한 또 다른 문제는 Unity와 같은 많은 라이브러리가 여러 스레드의 호출을 지원하도록 설계되지 않았다는 것입니다. 어떤 통화가 허용되고 어떤 통화가 금지되는지에주의를 기울이지 않으면 프레임 워크를 매우 쉽게 중단 할 수 있습니다.
이러한 추가 복잡성의 이유는 실제로 매우 간단합니다. 선점 형 멀티 태스킹 모델은 실제로 다른 스레드를 중단 할뿐만 아니라 다른 코어에서 스레드를 나란히 실행할 수 멀티 스레딩 모델 . 이것은 나오는 새로운 쿼드 코어 및 16 진수 코드 CPU를 실제로 활용할 수있는 유일한 방법이므로 판도라 상자를 열 수있는 유일한 방법이므로 매우 강력합니다. 멀티 스레딩 환경에서이 데이터를 관리하는 방법에 대한 동기화 규칙은 매우 잔인합니다. C ++ 세계에는 MEMORY_ORDER_CONSUME
멀티 스레딩 동기화의 한 가지 일흔 둘이 하나 인 코너에 관한 전체 기사 가 있습니다.
스레딩의 단점? 간단하다 : 어렵다. 전에는 본 적이없는 모든 종류의 버그를 발견 할 수 있습니다. 많은 경우가 종종 나타나는 "heisenbugs"이며 디버그 할 때 사라집니다. 이러한 도구를 다루기 위해 제공되는 도구는 매우 강력하지만 수준이 매우 낮습니다. 그것들은 사용하기 쉽게 디자인되지 않고 현대 칩의 아키텍처에서 효율적으로 설계되었습니다.
그러나 모든 CPU 성능을 사용하려면 필요한 도구가 필요합니다. 또한,이 있습니다 실제로는 OS 핸들 중단이 일어날 수있는 모든 질문을 할 수 있기 때문에 단순히 그들이 코 루틴과 함께보다 멀티 스레딩에 이해하기 쉽게 알고리즘.
코 루틴에 대한 솔직한 달의 의견도 저의 추천입니다. 스레드의 힘을 원한다면 커밋하십시오. 나가서 정말 공식적으로, 스레드를 배운다. 우리는 수십 년 동안 스레드에 대해 생각하는 가장 좋은 방법을 구성하여 안전하게 신뢰할 수있는 반복 가능한 결과를 조기에 얻고 성능을 추가하는 방법을 알아 냈습니다. 예를 들어, 모든 제정신 코스는 조건 변수를 가르치기 전에 뮤텍스를 가르칩니다. 원자를 다루는 모든 제정신 코스는 원자가 존재한다고 언급하기 전에 뮤텍스와 조건 변수를 완전히 가르칩니다. (참고 : 원자에 관한 제정신 튜토리얼은 없습니다.) 스레딩 조각을 배우려고하면 편두통을 구걸하고 있습니다.
join()
않지만 무언가가 필요합니다. 동기화를 수행 할 시스템을 설계 한 설계자가없는 경우 직접 작성해야합니다. 멀티 스레드 작업을하는 사람으로서, 컴퓨터가 안전하게 동기화하기 전에 컴퓨터가 어떻게 작동해야하는지에 대한 사람들의 정신 모델 (좋은 코스가 가르치는 것입니다)
join
. 필자의 요점은 스레딩의 가능한 성능 이점 중 일부를 쉽게 추구하는 것이 더 복잡한 스레딩 방식을 사용하는 것보다 더 큰 비율을 얻는 것보다 낫다는 것입니다.
가능한 가장 간단한 용어로 ...
실
스레드는 생성 시점을 결정하지 않으며 운영 체제 (예 : Windows)는 스레드 생성 시점을 결정합니다. 운영 체제는 거의 전적으로 스레드 스케줄링을 담당하며 실행할 스레드, 실행시기 및 기간을 결정합니다.
또한 스레드는 동 기적으로 (하나의 스레드가 차례로 실행 됨) 또는 비동기 적으로 (다른 CPU 코어에서 실행되는 다른 스레드) 실행될 수 있습니다. 비동기 적으로 실행할 수 있다는 것은 스레드가 문자 그대로 두 가지 작업을 동시에 수행하기 때문에 스레드가 같은 시간에 더 많은 작업을 수행 할 수 있음을 의미합니다. OS가 스케줄링을 잘하면 동기 스레드도 많은 작업을 수행합니다.
그러나이 추가 처리 성능에는 부작용이 있습니다. 예를 들어, 두 스레드가 동일한 리소스 (예 : 목록)에 액세스하려고 시도하고 각 스레드가 코드의 임의의 지점에서 임의로 중지 될 수있는 경우 두 번째 스레드의 수정은 첫 번째 스레드의 수정을 방해 할 수 있습니다. ( 경합 조건 및 교착 상태 참조 )
스레드는 오버 헤드가 많기 때문에 '무거운'것으로 간주됩니다. 즉, 스레드를 전환 할 때 시간이 많이 걸립니다.
코 루틴
스레드와 달리 코 루틴은 완전히 동기화되므로 한 시점에서 하나의 코 루틴 만 실행할 수 있습니다. 또한 코 루틴은 항복시기를 선택하므로, 코드에서 편리한 지점 (예 : 루프 사이클의 끝)에서 항복을 선택할 수 있습니다. 이것은 경쟁 조건 및 교착 상태와 같은 문제를 피하기가 훨씬 쉬울뿐만 아니라 코 루틴이 서로 협력하기 쉽도록합니다.
그러나 코 루틴이 제대로 생성되지 않으면 프로세서 시간이 많이 소요될 수 있으며 공유 리소스를 잘못 수정하면 여전히 버그가 발생할 수 있습니다.
코 루틴은 일반적으로 컨텍스트 전환이 필요하지 않으므로 빠르게 전환 할 수 있으며 매우 가볍습니다.
요약해서 말하자면:
실:
코 루틴 :
스레드와 코 루틴의 역할은 매우 유사하지만 작업 수행 방식이 다르므로 각각 다른 작업에 더 적합합니다. 스레드는 방해받지 않고 스스로 무언가를하는 데 집중 한 다음 완료되면 다시 신호를 보낼 수있는 작업에 가장 적합합니다. 코 루틴은 데이터를 공동으로 처리해야하는 많은 작은 단계와 작업으로 수행 할 수있는 작업에 가장 적합합니다.