본문으로 바로가기

쓰레드 프로그래밍 Thread

category 카테고리 없음 2024. 6. 17. 13:59

Tcl은 기본으로 여러 개의 인터프리터를 같은 스레드로 생성하는 방법을 채택하였습니다. 하지만, 각 인터프리터를 다른 쓰레드에 연결시키기 위해서는 Thread 확장 Tcl인터프리터를 사용해야 합니다. Thread 확장 Tcl인터프리터을 사용 하면, 다른 쓰레드 안의 인터프리터 사이로 통신을 할 수 있고, 다른 쓰레드의 결과를 얻거나 비동기로 처리하는 것이 가능해집니다.

쓰레드의 시도

Tcl의 멀티쓰레드 시도는 Tcl8.1부터였으며, Tcl소스코드내부에 testthread라는 숨겨진 커맨드가 있었습니다. 현재는 멀티쓰레드기능이 포함된 정식 Tcl버전이 배포되고 있습니다. :)

소스코드로의 빌드

최근에는 윈도우즈에서 gcc의 윈도우즈 버전인 MinGW를 사용하여, Tcl소스코드로부터 Tcl확장 버전을 빌드하여, 비교적 부담 없는 Tcl의 멀티 쓰레드 기능을 테스트할 수 있습니다. 소스코드로부터 멀티쓰레드 기능이 포함된(Tcl8.4.2부터 지원됨) tclsh, wish를 빌드하기 위해서는, -enable-threads옵션을 주어 빌드합니다. 빌드 후 결과 파일인 tcltest.exe와 tktest.exe는 tclsh.exe와 wish.exe의 멀티쓰레드 버전이 됩니다.

$ cd tcl8.4.2/win 
$ ./configure --enable-gcc --enable-threads 
$ make 
$ make tcltest.exe 

$ cd tk8.4.2/win 
$ ./configure --enable-gcc --enable-threads 
$ make 
$ make tktest.exe

최신의 ActiveTcl은 thread 버전과 그렇지 않은 버전을 배포하고 있으며, Tcl/Tk의 소스코드를 다시 빌드해야 하는 불편을 없앴습니다.

사용방법

간단한 멀티쓰레드의 기능을 테스트해봅니다.

 

create 커맨드를 사용하여 쓰레드를 생성합니다. 인자를 생략하면 이벤트 대기 상태의 쓰레드가 됩니다. 쓰레드가 정상적으로 생성되었다면 위의 그림과 같이 쓰레드 ID를 반환합니다.

 

인자에 스크립트를 지정하면 생성된 쓰레드로 스크립트를 실행합니다. 또한 스크립트의 실행이 끝나면 쓰레드가 자동적으로 삭제됩니다. 스크립트의 실행이 끝난 후에 쓰레드의 삭제를 막고 싶다면 쓰레드를 이벤트대기 상태로 해둡니다. 이때 vwait를 사용해도 되지만, wait커맨드도 사용할 수 있습니다.

 

다른 쓰레드에서 대기상태의 쓰레드에 send 커맨드로 스크립트를 송/수신할 수 있습니다. send 커맨드의 인자에는 송신지의 쓰레드의 쓰레드 ID와 스크립트를 지정합니다. 보통 send 커맨드로 송신한 스크립트의 결과는 동기화로 반환됩니다. send에 -async 옵션을 준다면 비동기로 처리되며, 코드의 실행 결과는 반환하지 않습니다.

 

위의 예는 다른 쓰레드로부터 다른 쓰레드의 변수값을 참조하고 있습니다. 모든 쓰레드 ID를 얻고 싶다면, names 커맨드를 사용합니다.

 

쓰레드의 존재 유/무 검사는 exists 커맨드를 사용합니다. 쓰레드 ID로 지정된 쓰레드가 존재하는 경우는 1, 아니면 0이 반환됩니다.

 

현재 쓰레드ID를 얻고 싶으면 id 커맨드를 사용합니다.

 

쓰레드를 삭제시 exit나 unwind 커맨드를 사용합니다. (Thread 2.2부터는 ::thread::exit에서 ::thread::unwind로 변경되었습니다.)

 

create 커맨드로 생성된 쓰레드에 실행 중인 스크립트 에러가 발생하고, 또한 그 에러를 catch로 감싸지 않으면 애플리케이션의 이상종료가 발생됩니다. 쓰레드 내부에서 발생한 에러는 errorproc로 에러 원인을 얻을 수 있습니다. 에러 프러시저를 정의해 두면 애플리케이션의 이상종료를 막을 수 있습니다.

 

에러 프로시져의 인자는, 에러가 발생한 쓰레드의 ID와 정보가 됩니다. 이 정보로 스크립트의 버그를 찾아낼 수 있습니다. ::thread::join과 ::thread::transfer는 Tcl8.4.x 버전과는 궁합이 맞지 않아 사용할 수 없다고 했습니다. join은 지정한 쓰레드가 종료될 때까지 호출한 쓰레드의 실행을 일시정지시키는 커맨드입니다. transfer는 오픈한 파일의 핸들을 다른 쓰레드에 전송하는 커맨드입니다. 그밖에 매뉴얼에는 나와 있지 않지만 아래와 같은 각각의 쓰레드 변수를 공유하고, 숨기는 등 여러 목적의 커맨드도 있습니다. sv_cond와 sv_mutex는 변수의 액세스를 제어하기 위한 커맨드입니다. 상세한 것은 쓰레드의 다른 문서를 참고하시기 바랍니다.

sv_get, sv_lappend, sv_incr, sv_append, sv_set, sv_unset, 
sv_array, sv_cond, sv_mutex

 

아래의 예는 각각 쓰레드의 변수를 공유합니다. 공유한 변수는 전부 배열 변수로써 취급하고, 변수명과 값으로 지정합니다.