그린 스레드
컴퓨터 프로그래밍에서 그린 스레드(Green thread)는 기반이 되는 운영체제 (OS)에 의해 기본적으로 스케줄링되지 않고, 런타임 라이브러리 또는 가상 머신 (VM)에 의해 스케줄링되는 스레드이다. 그린 스레드는 네이티브 OS 기능에 의존하지 않고 다중 스레드 환경을 에뮬레이트하며, 커널 공간 대신 사용자 공간에서 관리되어 네이티브 스레드 지원이 없는 환경에서도 작동할 수 있다.[1]
어원
[편집]그린 스레드는 자바 프로그래밍 언어의 원래 스레드 라이브러리 이름(버전 1.1에 출시되었고 버전 1.3에서는 네이티브 스레드로 전환되면서 폐기됨)에서 유래했다. 이 라이브러리는 썬 마이크로시스템즈의 그린 팀(The Green Team)에서 설계했다.[2]
역사
[편집]그린 스레드는 1997년부터 2000년 사이에 자바에서 잠시 사용되었다.
그린 스레드는 협력적 동시성을 통해 단일 운영체제 스레드를 공유하므로, 운영체제 스레드처럼 병렬 처리 성능 향상을 달성할 수 없다. 코루틴과 그린 스레드의 주요 이점은 구현의 용이성이다.
성능
[편집]멀티 코어 프로세서에서는 네이티브 스레드 구현이 여러 프로세서에 작업을 자동으로 할당할 수 있는 반면, 그린 스레드 구현은 일반적으로 그렇지 못하다.[1][3] 일부 VM에서는 그린 스레드를 훨씬 빠르게 시작할 수 있다. 그러나 단일 프로세서 컴퓨터에서는 가장 효율적인 모델이 아직 명확하게 결정되지 않았다.
리눅스 커널 버전 2.2(1999년 출시)를 실행하는 컴퓨터에서의 벤치마크는 다음을 보여주었다.[4]
- 그린 스레드는 스레드 활성화 및 동기화에서 리눅스 네이티브 스레드보다 훨씬 뛰어난 성능을 보인다.
- 리눅스 네이티브 스레드는 I/O 및 문맥 교환 작업에서 약간 더 나은 성능을 보인다.
그린 스레드가 블로킹 시스템 호출을 실행하면 해당 스레드뿐만 아니라 프로세스 내의 모든 스레드가 블록된다.[5] 이 문제를 피하려면 그린 스레드는 논블로킹 입출력 또는 비동기 입출력 작업을 사용해야 한다. 비록 사용자 측의 복잡성이 증가할 수 있지만, 그린 스레드를 구현하는 가상 머신이 각 I/O 작업에 대해 특정 I/O 프로세스(사용자에게 숨겨진)를 생성한다면 복잡성이 줄어들 수 있다.
네이티브 스레드 사용을 허용하고 스레드 활성화 및 동기화 오버헤드를 줄이는 메커니즘도 있다.
- 스레드 풀은 제한된 수의 스레드를 재사용하여 새 스레드 생성 비용을 줄인다.[6]
- 가상 머신과 네이티브 스레드를 사용하는 언어는 필요 없을 때 코드 블록 동기화를 피하기 위해 탈출 분석을 사용할 수 있다.[7]
자바 가상 머신의 그린 스레드
[편집]자바 1.1에서는 그린 스레드가 자바 가상 머신 (JVM)에서 사용되는 유일한 스레딩 모델이었다.[8] 적어도 솔라리스에서는 그랬다. 그린 스레드는 네이티브 스레드에 비해 몇 가지 제한 사항이 있어, 이후 자바 버전에서는 네이티브 스레드 선호로 변경되었다.[9][10]
예외는 저전력 장치용 운영체제와 자바 가상 머신의 혼합 형태인 Squawk 가상 머신이다. 이 가상 머신은 네이티브 코드 사용을 최소화하고 격리된 환경을 지원하기 위해 그린 스레드를 사용한다.
Kilim[11][12]과 Quasar[13][14]는 자바 컴파일러가 생성하는 자바 바이트코드를 수정하여 JVM의 최신 버전에서 그린 스레드를 구현하는 오픈 소스 프로젝트이다(Quasar는 코틀린과 클로저도 지원한다).
다른 언어의 그린 스레드
[편집]네이티브 스레드 대신 그린 스레드와 동등한 것을 구현하는 다른 프로그래밍 언어들도 있다. 예시:
- 치킨 스킴은 일급 연속체를 기반으로 하는 경량 사용자 수준 스레드를 사용한다.[15]
- 커먼 리스프[16]
- C파이썬은 버전 3.4부터 기본적으로 asyncio를 지원하며, greenlet, eventlet 및 gevent와 같은 대체 구현이 존재한다. PyPy[17]
- 크리스탈은 파이버를 제공한다.[18]
- D는 비동기 입출력에 사용되는 파이버를 제공한다.[19]
- Dyalog APL은 이를 스레드라고 부른다.[20]
- 얼랭[21]
- Go는 고루틴이라고 불리는 것을 구현한다.[22]
- 하스켈[22]
- 줄리아는 Task에 그린 스레드를 사용한다.
- 림보[23]
- 루아는 동시성을 위해 코루틴을 사용한다. 루아 5.2는 lua_yieldk, lua_callk, lua_pcallk 함수를 통해 진정한 C 코루틴 의미론을 제공한다. CoCo 확장은 루아 5.1에서 진정한 C 코루틴 의미론을 허용한다.
- 님은 비동기 I/O 및 코루틴을 제공한다.
- OCaml은 버전 5.0부터 Domainslib.Task 모듈을 통해 그린 스레드를 지원한다.
- Occam은 커뮤니케이팅 시퀜셜 프로세스의 기원 때문에 스레드 대신 프로세스라는 용어를 선호한다.
- 펄은 코루틴을 통해 그린 스레드를 지원한다.
- PHP는 파이버와 코루틴을 통해 그린 스레드를 지원한다.
- 래킷 (Places를 통해 네이티브 스레드도 사용 가능[24])
- 버전 1.9 이전의 루비[25]
- Concurrent ML의 SML/NJ 구현
- 스몰토크 (대부분의 방언: 스퀵, VisualWorks, GNU Smalltalk 등)
- 스택리스 파이썬은 마이크로 스레드(태스클릿이라고 함)를 통해 선점형 멀티태스킹 또는 협력적 멀티태스킹을 지원한다.[26]
- Tcl은 코루틴과 이벤트 루프를 가지고 있다.[27]
얼랭 가상 머신에는 그린 프로세스라고 불릴 만한 것이 있다. 이들은 운영체제 프로세스와 유사하지만(스레드처럼 상태를 공유하지 않는다) 얼랭 런타임 시스템(erts) 내에서 구현된다. 이들은 때때로 그린 스레드라고 불리지만, 표준 그린 스레드와는 상당한 차이가 있다.
GHC 하스켈의 경우, 구성 가능한 타임아웃 후 첫 번째 할당에서 컨텍스트 전환이 발생한다. GHC 스레드는 수명 동안 하나 이상의 OS 스레드에서 실행될 수도 있으며(GHC 스레드와 OS 스레드 간에는 다대다 관계가 있다), 이는 대칭형 다중 처리 머신에서 병렬 처리를 가능하게 하면서도 사용 가능한 코어 수에 필요한 것보다 더 많은 비용이 드는 OS 스레드를 생성하지 않는다.
대부분의 스몰토크 가상 머신은 평가 단계를 세지 않지만, VM은 외부 신호(예: 타이머 만료 또는 I/O 사용 가능)에 따라 실행 중인 스레드를 선점할 수 있다. 일반적으로 라운드 로빈 스케줄링이 사용되어, 주기적으로 깨어나는 고우선순위 프로세스가 효과적으로 시분할 선점을 구현한다.
[
[(Delay forMilliseconds: 50) wait] repeat
] forkAt: Processor highIOPriority
QKS 스몰토크와 같은 다른 구현은 항상 시분할 방식이다. 대부분의 그린 스레드 구현과 달리 QKS는 우선순위 역전 방지도 지원한다.
자바 가상 머신의 가상 스레드와의 차이점
[편집]가상 스레드는 자바 19에서 미리보기 기능으로 도입되었고[28] 자바 21에서 안정화되었다.[29] 가상 스레드와 그린 스레드의 중요한 차이점은 다음과 같다.
- 가상 스레드는 기존 (비가상) 플랫폼 스레드 및 스레드 풀과 공존한다.
- 가상 스레드는 추상화를 보호한다.
- 그린 스레드와 달리 가상 스레드에서 슬립 상태에 들어가도 기본 캐리어 스레드가 블록되지 않는다.
- 스레드 로컬 변수 사용은 강조되지 않으며, 스코프 값은 더 가벼운 대안으로 제안된다.[30]
- 가상 스레드는 JVM의 특수 `jdk.internal.vm.Continuation` 클래스 지원을 활용하여 저렴하게 일시 중단 및 재개될 수 있다.
- 가상 스레드는 블로킹 호출을 처리할 때 가능한 경우 캐리어 스레드에서 투명하게 분리되며, 그렇지 않은 경우 플랫폼 스레드 수를 늘려 보상한다.
같이 보기
[편집]각주
[편집]- ↑ 가 나 Sintes, Tony (April 13, 2001). “Four for the ages”. 《JavaWorld》. 2020년 7월 15일에 원본 문서에서 보존된 문서. 2020년 7월 14일에 확인함.
Green threads, the threads provided by the JVM, run at the user level, meaning that the JVM creates and schedules the threads itself. Therefore, the operating system kernel doesn't create or schedule them. Instead, the underlying OS sees the JVM only as one thread. Green threads prove inefficient for a number of reasons. Foremost, green threads cannot take advantage of a multiprocessor system(...) Thus, the JVM threads are bound to run within that single JVM thread that runs inside a single processor.
- ↑ “Java Technology: The Early Years”. 《java.sun.com》. 2014년 12월 22일. 2008년 5월 30일에 원본 문서에서 보존된 문서.
- ↑ “What is the difference between "green" threads and "native" threads?”. 《jguru.com》. 2000년 9월 6일. 2009년 6월 1일에 확인함.
On multi-CPU machines, native threads can run more than one thread simultaneously by assigning different threads to different CPUs. Green threads run on only one CPU.
- ↑ 틀:Cite CiteSeerX
- ↑ Stallings, William (2008). 《Operating Systems, Internal and Design Principles》. New Jersey: Prentice Hall. 171쪽. ISBN 9780136006329.
- ↑ Sieger, Nick (2011년 7월 22일). “Concurrency in JRuby”. Engine Yard. 2014년 1월 30일에 원본 문서에서 보존된 문서. 2013년 1월 26일에 확인함.
For systems with large volumes of email, this naive approach may not work well. Native threads carry a bigger initialization cost and memory overhead than green threads, so JRuby normally cannot support more than about 10,000 threads. To work around this, we can use a thread pool.
- ↑ Goetz, Brian (2005년 10월 18일). “Java theory and practice: Synchronization optimizations in Mustang”. IBM. 2013년 1월 26일에 확인함.
- ↑ “Java Threads in the Solaris Environment – Earlier Releases”. 오라클 코퍼레이션. 2013년 1월 26일에 확인함.
As a result, several problems arose: Java applications could not interoperate with existing MT applications in the Solaris environment, Java threads could not run in parallel on multiprocessors, An MT Java application could not harness true OS concurrency for faster applications on either uniprocessors or multiprocessors. To substantially increase application performance, the green threads library was replaced with native Solaris threads for Java on the Solaris 2.6 platform; this is carried forward on the Solaris 7 and Solaris 8 platforms.
- ↑ “Threads: Green or Native”. SCO 그룹. 2013년 1월 26일에 확인함.
The performance benefit from using native threads on an MP machine can be dramatic. For example, using an artificial benchmark where Java threads are doing processing independent of each other, there can be a three-fold overall speed improvement on a 4-CPU MP machine.
- ↑ “Threads: Green or Native”. codestyle.org. 2013년 1월 16일에 원본 문서에서 보존된 문서. 2013년 1월 26일에 확인함.
There is a significant processing overhead for the JVM to keep track of thread states and swap between them, so green thread mode has been deprecated and removed from more recent Java implementations.
- ↑ “kilim”. 《GitHub》. 2016년 6월 9일에 확인함.
- ↑ “Kilim”. 《www.malhar.net》. 2016년 6월 9일에 확인함.
- ↑ “Quasar Code on GitHub”. 《깃허브》.
- ↑ “Parallel Universe”. 2015년 12월 22일에 원본 문서에서 보존된 문서. 2015년 12월 6일에 확인함.
- ↑ “Chicken Scheme”. 2017년 11월 5일에 확인함.
- ↑ “thezerobit/green-threads”. 《GitHub》. 2016년 4월 8일에 확인함.
- ↑ “Application-level Stackless features – PyPy 4.0.0 documentation”. 2015년 12월 6일에 확인함.
- ↑ “Concurrency: GitBook”. 《crystal-lang.org》. 2018년 4월 3일에 확인함.
- ↑ “Fibers - Dlang Tour”. 《tour.dlang.org》. 2022년 5월 2일에 확인함.
- ↑ “Threads: Overview”. 《Dyalog APL 17.0 Help》. 2018년 12월 14일에 확인함.
A thread is a strand of execution in the APL workspace.
- ↑ joeerl (2018년 6월 23일). “Erlang processes are emulated in the Erlang VM, like Green threads - we like them since this simplifies many proble…” (트윗).
- ↑ 가 나 “Go and Dogma”. 《research!rsc》. 2017년 1월 14일에 확인함.
for example both Go and Haskell need some kind of “green threads”, so there are more shared runtime challenges than you might expect.
- ↑ “The Limbo Programming Language”. 《www.vitanuova.com》. 2017년 6월 19일에 원본 문서에서 보존된 문서. 2019년 4월 1일에 확인함.
- ↑ “Racket Places”. 2011년 10월 13일에 확인함.
Places enable the development of parallel programs that take advantage of machines with multiple processors, cores, or hardware threads. A place is a parallel task that is effectively a separate instance of the Racket virtual machine.
- ↑ “Multithreading in the MRI Ruby Interpreter | BugFactory”. 2024년 6월 18일에 확인함.
- ↑ “Stackless.com: About Stackless”. 2012년 2월 27일에 원본 문서에서 보존된 문서. 2008년 8월 27일에 확인함.
A round robin scheduler is built in. It can be used to schedule tasklets either cooperatively or preemptively.
- ↑ “Tcl event loop”. 2015년 12월 6일에 확인함.
- ↑ “JEP 425: Virtual Threads (Preview)”. 2024년 1월 25일에 확인함.
- ↑ “JEP 444: Virtual Threads”. 2024년 1월 25일에 확인함.
- ↑ “JEP 464: Scoped Values (Second Preview)”. 2024년 1월 25일에 확인함.
외부 링크
[편집]- "Four for the ages", 그린 스레드에 대한 JavaWorld 기사
- Java 스레드 FAQ의 그린 스레드