스레드 (컴퓨팅)
스레드(thread)는 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위를 말한다. 일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있다. 이러한 실행 방식을 멀티스레드(multithread)라고 한다.
프로세스와 스레드의 비교
멀티프로세스와 멀티스레드는 양쪽 모두 여러 흐름이 동시에 진행된다는 공통점을 가지고 있다. 하지만 멀티프로세스에서 각 프로세스는 독립적으로 실행되며 각각 별개의 메모리를 차지하고 있는 것과 달리 멀티스레드는 프로세스 내의 메모리를 공유해 사용할 수 있다. 또한 프로세스 간의 전환 속도보다 스레드 간의 전환 속도가 빠르다.
멀티스레드의 다른 장점은 CPU가 여러 개일 경우에 각각의 CPU가 스레드 하나씩을 담당하는 방법으로 속도를 높일 수 있다는 것이다. 이러한 시스템에서는 여러 스레드가 실제 시간상으로 동시에 수행될 수 있기 때문이다.
멀티스레드의 단점에는 각각의 스레드 중 어떤 것이 먼저 실행될지 그 순서를 알 수 없다는 것이 있다. 예를 들어, 두 스레드가 특정 공유 변수 i의 값을 1 증가시키는 명령을 실행할 때, 다음과 같은 방식으로 수행될 수 있다.
- 공유되는 변수 i의 값을 레지스터에 저장
- 레지스터의 값을 1 증가시킨다.
- 변수 i에 그 값을 저장한다.
이때 두 스레드가 실행될 때 어떤 스레드가 먼저 실행될지는 보장되지 않으며, 만약 다음과 같은 순서로 실행된다면:
| 스레드 | 동작 | i의 값 | 스레드 1의 레지스터 | 스레드 2의 레지스터 |
|---|---|---|---|---|
| 스레드 1 | i의 값을 레지스터에 저장 | 0 | 0 | |
| 스레드 1 | 레지스터 값을 1 증가 | 0 | 1 | |
| 스레드 1 | i에 값 저장 | 1 | 1 | |
| 스레드 2 | i의 값을 레지스터에 저장 | 1 | 1 | 1 |
| 스레드 2 | 레지스터 값을 1 증가 | 1 | 1 | 2 |
| 스레드 2 | i에 값 저장 | 2 | 1 | 2 |
최종 결과로 i는 2가 증가된다. 하지만 다음과 같이 실행된다면:
| 스레드 | 동작 | i의 값 | 스레드 1의 레지스터 | 스레드 2의 레지스터 |
|---|---|---|---|---|
| 스레드 1 | i의 값을 레지스터에 저장 | 0 | 0 | |
| 스레드 2 | i의 값을 레지스터에 저장 | 0 | 0 | 0 |
| 스레드 1 | 레지스터 값을 1 증가 | 0 | 1 | 0 |
| 스레드 2 | 레지스터 값을 1 증가 | 0 | 1 | 1 |
| 스레드 1 | i에 값 저장 | 1 | 1 | 1 |
| 스레드 2 | i에 값 저장 | 1 | 1 | 1 |
최종 결과로 i는 1이 증가되고, 이것은 원래 프로그램의 의도(각각의 스레드가 i를 1씩 증가하는 동작)와 다를 수 있다. 또한 이러한 문제는 스레드의 실행 조건에 따라 결과가 다르게 나오므로, 오류가 발생했을 때 원인을 찾기가 힘들다. 이러한 문제를 경쟁 조건이라고 하며, 문제를 막기 위해 세마포어와 같은 방법을 통해 공유 데이터에 접근하는 스레드의 개수를 한개 이하로 유지하는 방법을 사용할 수 있다.
스레드의 종류
스레드를 지원하는 주체에 따라 2가지로 나눌 수 있다.
사용자 레벨 스레드 (User-Level Thread)
사용자 스레드는 커널 영역의 상위에서 지원되며 일반적으로 사용자 레벨의 라이브러리를 통해 구현되며, 라이브러리는 스레드의 생성 및 스케줄링 등에 관한 관리 기능을 제공한다. 동일한 메모리 영역에서 스레드가 생성 및 관리되므로 속도가 빠른 장점이 있는 반면, 여러 개의 사용자 스레드 중 하나의 스레드가 시스템 호출 등으로 중단되면 나머지 모든 스레드 역시 중단되는 단점이 있다. 이는 커널이 프로세스 내부의 스레드를 인식하지 못하며 해당 프로세스를 대기 상태로 전환시키기 때문이다.
커널 레벨 스레드 (Kernel-Level Thread)
커널 스레드는 운영체제가 지원하는 스레드 기능으로 구현되며, 커널이 스레드의 생성 및 스케줄링 등을 관리한다. 스레드가 시스템 호출 등으로 중단되더라도, 커널은 프로세스 내의 다른 스레드를 중단시키지 않고 계속 실행시켜준다. 다중처리기 환경에서 커널은 여러 개의 스레드를 각각 다른 처리기에 할당할 수 있다. 다만, 사용자 스레드에 비해 생성 및 관리하는 것이 느리다.
스레드 데이터
스레드 기본 데이터
스레드도 프로세스와 마찬가지로 하나의 실행 흐름이므로 실행과 관련된 데이터가 필요하다. 일반적으로 스레드는 자신만의 고유한 스레드 ID, 프로그램 카운터, 레지스터 집합, 스택을 가진다. 코드, 데이터, 파일 등 기타 자원은 프로세스 내의 다른 스레드와 공유한다.
스레드 특정 데이터
위의 기본 데이터 외에도 하나의 스레드에만 연관된 데이터가 필요한 경우가 있는데, 이런 데이터를 스레드 특정 데이터(Thread-Specific Data, 줄여서 TSD)라고 한다. 멀티스레드 프로그래밍 환경에서 모든 스레드는 프로세스의 데이터를 공유하고 있지만, 특별한 경우에는 개별 스레드만의 자료 공간이 필요하다. 예를 들어 여러 개의 트랜잭션을 스레드로 처리할 경우, 각각의 트랜잭션 ID를 기억하고 있어야 하는데, 이때 TSD가 필요하다. TSD는 여러 스레드 라이브러리들이 지원하는 기능 중의 하나이다.
프로세스 관리의 변화
멀티스레드 환경이 확산됨에 따라 전통적인 프로세스 관리 방식에도 변화가 필요해졌다. 예를 들어, fork 또는 exec와 같은 시스템 호출시에 어떻게 처리할 것인가 하는 문제가 대두된 것이다.
- fork 문제 : 어떤 프로세스 내의 스레드가 fork를 호출하면 모든 스레드를 가진 프로세스를 생성할 것인지, 아니면 fork를 요청한 스레드만 가진 프로세스를 생성할 것인지 하는 문제이다. 유닉스에서는 각각 2가지 버전의 fork를 지원하고 있다.
- exec 문제 : fork를 통해 모든 스레드를 복제하고 난 후, exec를 수행한다면 모든 스레드들이 초기화된다. 그렇다면 교체될 스레드를 복제하는 작업은 필요가 없기 때문에 애초에 fork를 요청한 스레드만을 복제했어야 한다. 한편, fork를 한 후에 exec를 수행하지 않는다면 모든 스레드를 복제할 필요가 있는 경우도 있다
같이 보기
외부 링크
모듈:Authority_control 159번째 줄에서 Lua 오류: attempt to index field 'wikibase' (a nil value).
- 스크립트 오류가 있는 문서
- 잘못된 파일 링크가 포함된 문서
- 위키데이터 속성 P18을 사용하는 문서
- 위키데이터 속성 P41을 사용하는 문서
- 위키데이터 속성 P94를 사용하는 문서
- 위키데이터 속성 P117을 사용하는 문서
- 위키데이터 속성 P154를 사용하는 문서
- 위키데이터 속성 P213을 사용하는 문서
- 위키데이터 속성 P227을 사용하는 문서
- 위키데이터 속성 P242를 사용하는 문서
- 위키데이터 속성 P244를 사용하는 문서
- 위키데이터 속성 P245를 사용하는 문서
- 위키데이터 속성 P268을 사용하는 문서
- 위키데이터 속성 P269를 사용하는 문서
- 위키데이터 속성 P271을 사용하는 문서
- 위키데이터 속성 P347을 사용하는 문서
- 위키데이터 속성 P349를 사용하는 문서
- 위키데이터 속성 P350을 사용하는 문서
- 위키데이터 속성 P373을 사용하는 문서
- 위키데이터 속성 P380을 사용하는 문서
- 위키데이터 속성 P396을 사용하는 문서
- 위키데이터 속성 P409를 사용하는 문서
- 위키데이터 속성 P428을 사용하는 문서
- 위키데이터 속성 P434를 사용하는 문서
- 위키데이터 속성 P435를 사용하는 문서
- 위키데이터 속성 P436을 사용하는 문서
- 위키데이터 속성 P454를 사용하는 문서
- 위키데이터 속성 P496을 사용하는 문서
- 위키데이터 속성 P549를 사용하는 문서
- 위키데이터 속성 P650을 사용하는 문서
- 위키데이터 속성 P651을 사용하는 문서
- 위키데이터 속성 P691을 사용하는 문서
- 위키데이터 속성 P716을 사용하는 문서
- 위키데이터 속성 P781을 사용하는 문서
- 위키데이터 속성 P791을 사용하는 문서
- 위키데이터 속성 P864를 사용하는 문서
- 위키데이터 속성 P865를 사용하는 문서
- 위키데이터 속성 P886을 사용하는 문서
- 위키데이터 속성 P902를 사용하는 문서
- 위키데이터 속성 P906을 사용하는 문서
- 위키데이터 속성 P947을 사용하는 문서
- 위키데이터 속성 P950을 사용하는 문서
- 위키데이터 속성 P966을 사용하는 문서
- 위키데이터 속성 P982를 사용하는 문서
- 위키데이터 속성 P1003을 사용하는 문서
- 위키데이터 속성 P1004를 사용하는 문서
- 위키데이터 속성 P1005를 사용하는 문서
- 위키데이터 속성 P1006을 사용하는 문서
- 위키데이터 속성 P1015를 사용하는 문서
- 위키데이터 속성 P1045를 사용하는 문서
- 위키데이터 속성 P1048을 사용하는 문서
- 위키데이터 속성 P1053을 사용하는 문서
- 위키데이터 속성 P1146을 사용하는 문서
- 위키데이터 속성 P1153을 사용하는 문서
- 위키데이터 속성 P1157을 사용하는 문서
- 위키데이터 속성 P1186을 사용하는 문서
- 위키데이터 속성 P1225를 사용하는 문서
- 위키데이터 속성 P1248을 사용하는 문서
- 위키데이터 속성 P1273을 사용하는 문서
- 위키데이터 속성 P1315를 사용하는 문서
- 위키데이터 속성 P1323을 사용하는 문서
- 위키데이터 속성 P1330을 사용하는 문서
- 위키데이터 속성 P1362를 사용하는 문서
- 위키데이터 속성 P1368을 사용하는 문서
- 위키데이터 속성 P1375를 사용하는 문서
- 위키데이터 속성 P1407을 사용하는 문서
- 위키데이터 속성 P1556을 사용하는 문서
- 위키데이터 속성 P1584를 사용하는 문서
- 위키데이터 속성 P1695를 사용하는 문서
- 위키데이터 속성 P1707을 사용하는 문서
- 위키데이터 속성 P1736을 사용하는 문서
- 위키데이터 속성 P1886을 사용하는 문서
- 위키데이터 속성 P1890을 사용하는 문서
- 위키데이터 속성 P1907을 사용하는 문서
- 위키데이터 속성 P1908을 사용하는 문서
- 위키데이터 속성 P1960을 사용하는 문서
- 위키데이터 속성 P1986을 사용하는 문서
- 위키데이터 속성 P2041을 사용하는 문서
- 위키데이터 속성 P2163을 사용하는 문서
- 위키데이터 속성 P2174를 사용하는 문서
- 위키데이터 속성 P2268을 사용하는 문서
- 위키데이터 속성 P2349를 사용하는 문서
- 위키데이터 속성 P2418을 사용하는 문서
- 위키데이터 속성 P2456을 사용하는 문서
- 위키데이터 속성 P2484를 사용하는 문서
- 위키데이터 속성 P2558을 사용하는 문서
- 위키데이터 속성 P2750을 사용하는 문서
- 위키데이터 속성 P2980을 사용하는 문서
- 위키데이터 속성 P3223을 사용하는 문서
- 위키데이터 속성 P3233을 사용하는 문서
- 위키데이터 속성 P3348을 사용하는 문서
- 위키데이터 속성 P3372를 사용하는 문서
- 위키데이터 속성 P3407을 사용하는 문서
- 위키데이터 속성 P3430을 사용하는 문서
- 위키데이터 속성 P3544를 사용하는 문서
- 위키데이터 속성 P3562를 사용하는 문서
- 위키데이터 속성 P3563을 사용하는 문서
- 위키데이터 속성 P3601을 사용하는 문서
- 위키데이터 속성 P3723을 사용하는 문서
- 위키데이터 속성 P3788을 사용하는 문서
- 위키데이터 속성 P3829를 사용하는 문서
- 위키데이터 속성 P3863을 사용하는 문서
- 위키데이터 속성 P3920을 사용하는 문서
- 위키데이터 속성 P3993을 사용하는 문서
- 위키데이터 속성 P4038을 사용하는 문서
- 위키데이터 속성 P4055를 사용하는 문서
- 위키데이터 속성 P4114를 사용하는 문서
- 위키데이터 속성 P4143을 사용하는 문서
- 위키데이터 속성 P4186을 사용하는 문서
- 위키데이터 속성 P4423을 사용하는 문서
- 위키데이터 속성 P4457을 사용하는 문서
- 위키데이터 속성 P4534를 사용하는 문서
- 위키데이터 속성 P4535를 사용하는 문서
- 위키데이터 속성 P4581을 사용하는 문서
- 위키데이터 속성 P4613을 사용하는 문서
- 위키데이터 속성 P4955를 사용하는 문서
- 위키데이터 속성 P5034를 사용하는 문서
- 위키데이터 속성 P5226을 사용하는 문서
- 위키데이터 속성 P5288을 사용하는 문서
- 위키데이터 속성 P5302를 사용하는 문서
- 위키데이터 속성 P5321을 사용하는 문서
- 위키데이터 속성 P5368을 사용하는 문서
- 위키데이터 속성 P5504를 사용하는 문서
- 위키데이터 속성 P5587을 사용하는 문서
- 위키데이터 속성 P5736을 사용하는 문서
- 위키데이터 속성 P5818을 사용하는 문서
- 위키데이터 속성 P6213을 사용하는 문서
- 위키데이터 속성 P6734를 사용하는 문서
- 위키데이터 속성 P6792를 사용하는 문서
- 위키데이터 속성 P6804를 사용하는 문서
- 위키데이터 속성 P6829를 사용하는 문서
- 위키데이터 속성 P7293을 사용하는 문서
- 위키데이터 속성 P7303을 사용하는 문서
- 위키데이터 속성 P7314를 사용하는 문서
- 위키데이터 속성 P7902를 사용하는 문서
- 위키데이터 속성 P8034를 사용하는 문서
- 위키데이터 속성 P8189를 사용하는 문서
- 위키데이터 속성 P8381을 사용하는 문서
- 위키데이터 속성 P8671을 사용하는 문서
- 위키데이터 속성 P8980을 사용하는 문서
- 위키데이터 속성 P9070을 사용하는 문서
- 위키데이터 속성 P9692를 사용하는 문서
- 위키데이터 속성 P9725를 사용하는 문서
- 위키데이터 속성 P9984를 사용하는 문서
- 위키데이터 속성 P10020을 사용하는 문서
- 위키데이터 속성 P10299를 사용하는 문서
- 위키데이터 속성 P10608을 사용하는 문서
- 위키데이터 속성 P10832를 사용하는 문서
- 위키데이터 속성 P11249를 사용하는 문서
- 위키데이터 속성 P11646을 사용하는 문서
- 위키데이터 속성 P11729를 사용하는 문서
- 위키데이터 속성 P12204를 사용하는 문서
- 위키데이터 속성 P12362를 사용하는 문서
- 위키데이터 속성 P12754를 사용하는 문서
- 위키데이터 속성 P13049를 사용하는 문서
- 스레드
- 병행 컴퓨팅