4 장스레드 (Threads) 프로세스 = 자원 + PC 스레드 : 새 PC (a thread of control) 로같은 address space 를실행하는 fork 와유사 스레드 (Threads) 개요 경량프로세스 (LWP; lightweight process) = 스레드» CPU 를이용하는기본단위» thread ID, PC, 레지스터세트, 스택영역을가짐» 스레드들은서로같은프로세스의 code section, data section, OS resources-open files, signals 를공유 ( 그림 4.1)» ( 예 1) web browser image 와 text 를 display 하는 thread network 에서데이터를가져오는 thread» ( 예 2) word processor graphics 를 display 하는 thread keystrokes 를읽어오는 thread spelling 과 grammar 를검사하는 thread 중량프로세스 (heavyweight process) = 1 thread 를가진 task 비교» 경량프로세스의문맥교환 : CPU switching, thread context switch 레지스터세트교환만» 중량프로세스의문맥교환 : process switching, context switching 레지스터세트교환과메모리관련작업도 (virtual memory page table 변경등 ) 4.1
Single and Multithreaded Processes 4.2
Single and Multithreaded Processes 4.3
스레드 (Threads) 개요 제어» 다중스레드제어 (multiple-thread control) 자신의 PC, stack, 비독립적 (no protection)» 다중프로세스제어 (multiple-process control) 자신의 PC, stack, address space, 독립적 (protection) 스레드의특성» CPU공유» 준비, 수행, 대기상태» 자식 thread생성» block ( 예1) 웹서버구현» a single process : client의대기시간이매우기어짐» multiple process : client의요청이올때마다새 process 생성, overhead» multithreaded single process : 서버는 thread 생성하여 client의요청기다리다요청이오면새 thread 생성하여서비스, 효율적 ( 예2) 생산자소비자문제» 2 threads 로구현하면좋음 (better if on 2 processors) Thread의장점» 빠른응답 (responsiveness)» 자원공유 (resource sharing)» 경제성 (economy)» 다중처리기구조이용 (utilization of multiprocessor architecture) 4.4
사용자스레드와커널스레드 (User and kernel Threads) 사용자스레드 (User Threads)» user level의 thread library로구현 : 라이브러리가 thread 생성, 스케줄링, 관리담당» 불공평한스케줄링 (unfair scheduling)» 스위칭이빠름 (switching is fast)» single thread인 kernel에서사용자수준스레드가 blocking system call을수행할경우 system call 완료까지다른모든스레드들은대기해야함» Three primary thread libraries: i POSIX Pthreads: POSIX (Portable Operating System Interface) standard (IEEE 1003.1c) APIs (Solaris, Linux, Mac OS X) Java Threads Win32 Threads 커널스레드 (Kernel Threads)» 커널이 thread생성, 스케줄링, 관리담당» 공평한스케줄링 (fair scheduling)» 스위칭시간이김 (switching is time consuming) : interrupt 처리때문» blocking system call 수행시커널이다른 thread 실행시킬수있음» Examples Windows XP/2000 Solaris Linux Tru64 UNIX Mac OS X 혼합접근 (hybrid approach) : Solaris 2 4.5
사용자스레드와커널스레드 (User and kernel Threads) kernel 자체 (system call 수행방법 )» single tasking : 초기 Unix kernel : 공유자료접근동기화불필요» multi tasking 동기적인시스템» Mach kernel : 스레드들은동기적임 (threads are synchronous), 다른스레드가제어를넘겨준다음에만수행가능 ( 공유데이타변경중에는제어를넘겨주지않음 ) 비동기적인시스템 : 잠금기법 (locking mechanism) 필요 4.6
다중스레드모델 (Multithreading Models) Many-to-One Model : 초기 Solaris Green threads, GNU Portable Threads» 다수의 user-level thread가하나의 kernel thread로매핑» 한 thread가 blocking system call하면전체프로세스 block One-to-One Model : Solaris 9 과이후버전, Linux, OS/2, Windows 95, 98, NT, 2000, XP» 각 user-level thread 가하나의 a kernel thread로매핑» 한 thread 가 blocking system call 해도다른 thread 실행가능» User thread 생성마다 kernel thread 생성해야함» 동시성이좋음 (more concurrency): multiprocessors에서병렬처리 (parallel processing) 가능 Many-to-Many Model : Solaris 9 prior, Windows NT/2000 ThreadFiber package» 다수의 user-level thread들이더적거나같은수의 kernel threads들로매핑 (multiplexed)» 동시성이덜좋음 (less concurrency): 커널은한순간에하나의 kernel thread만스케줄» 특별한경우 : two-level model: 하나의 user-level thread가하나의 kernel thread로연결되는경우도지원 : Solaris 8과이전버전, IRIX, Digital Unix, HP Tru64 UNIX 4.7
Many-to-One Model 4.8
One-to-one Model 4.9
Many-to-Many y Model 4.10
Two-level Model 4.11
Solaris 2 Threads 솔라리스 (Solaris) 2.x SunOS Release 4.x - Solaris 1.x SunOS Release 5.x - Solaris 2.x Solaris 2 의지원기능» kernel수준과 user수준에서스레드지원» symmetric multiprocessing( 대칭적다중프로세싱 ) 각 process가 OS가짐 Master-slave의반대» real-time scheduling( 실시간스케줄링 ) 스레드들 : LWP(Light Weight Processes) = a virtual CPU» user-level (thread API 들의 library) thread ID, register set(pc, stack pointer), stack, 우선순위 switching(linking with thread) 이빠르다 문맥교환없고 CPU switching( 스레드문맥교환 ) 있음 종류» bound: LWP 에영원히연결됨, quick response 가능» unbound: LWP 풀에 multiplexed» intermediate-level = LWP kernel 자료구조, user level l thread 의 register set, 메모리와계정정보 비교적느리다.» kernel-level(cpu 스케줄링대상 ) 약간의자료구조 : stack, kernel registers, LWP pointer, 우선순위, 스케줄링정보 switching 이비교적빠르다. 4.12
Solaris 2 Threads» Solaris 2의스레드 Many LWP, many CPU N user-level thread <-> l LWP 1 LWP <-> 1 Kernel-level thread = 1 system call N Kernel-level thread <-> 1 CPU» Solaris 에서 ps elc해보면lwp 정보알수있음» ( 예 ) 동시에 5개화일읽기 -> 5 LWP필요 각화일읽기는 Kernel 안에서 I/O완료를기다려야할경우» Solaris 2 에서 한 task는한 I/O완료를기다리는동안 block될필요가없음 : 어떤작업의한 LWP(kernel thread) 가 I/O 완료를기다리게되더라도 CPU는그작업의다른 LWP(kernel thread) 로이동하여작업수행을계속 thread library가최적의성능을지원하도록동적으로 LWP 풀의수조절» 한프로세스안의모든 LWP 봉쇄되어실행가능 LWP 없는데대기스레드있으면새 LWP 생성» 일정기간 ( 예, 5 분 ) 사용되지않은 LWP 삭제» 참조 Solaris 2.x : System Administrator s Guide, Threads Primer: A Guide to Multithreaded Programming, Bil Lewis, Daniel J.Berg, Prentice Hall, 1996. 4.13
Solaris 2 Threads 4.14
Solaris Process (PCB) 4.15
Threads 지원방법 Kernel(OS) 지원» Solaris Threads fork1(): fork() 와달리호출한스레드와연관된자료구조만복제 fork() + exec(): exec() 로주소공간제거 fork() + POSIX threads library (-lpthread)» Linux Threads Linux refers to them as tasks rather than threads Thread creation is done through h clone() system call clone() allows a child task to share the address space of the parent task (process) Library 지원» POSIX Phread: /usr/include/pthread.h» Solaris Thread: /usr/include/thread.h /i /th dh» Windows XP Thread: Win32 library multithreading APIs Implements the one-to-one mapping Each thread contains» Athreadid» Register set» Separate user and kernel stacks» Private data storage area The register set, stacks, and private storage area are known as the context of the threads The primary data structures of a thread include:» ETHREAD (executive thread block)» KTHREAD (kernel thread block)» TEB (thread environment block) Language 지원 : Java Thread 뿐» main(): a single thread» 다른 thread들생성, 관리하는명령지원 4.16
Linux Threads 4.17
Windows XP Threads 4.18
Pthreads #include <pthread.h> #include <stdio.h> int sum; /* this data is shared by the thread(s) */ void *runner(void *param); /* the thread */ main(int argc, char *argv[]) pthread_t t tid; /* the thread identifier */ pthread_attr_t attr; /* set of attributes for the thread */ /* get the default attributes */ pthread_attr_init(&attr); /* create the thread */ pthread_create(&tid,&attr,runner,argv[1]); /* now wait for the thread to exit */ pthread_join(tid,null); printf("sum = %d n",sum); void *runner(void *param) int upper = atoi(param); int i; sum = 0; if (upper > 0) for (i = 1; i <= upper; i++) sum += i; pthread_exit(0); 4.19
Win32 Threads /** * This program creates a separate thread using the CreateThread() system c * * Figure 4.10 * * @author Gagne, Galvin, Silberschatz * Operating System Concepts - Eighth Edition * Copyright John Wiley & Sons - 2009. */ #include <stdio.h> #include <windows.h> int main(int argc, char *argv[]) DWORD ThreadId; HANDLE ThreadHandle; int Param; // do some basic error checking if (argc!= 2) fprintf(stderr,"an integer parameter is required\n"); return -1; Param = atoi(argv[1]); DWORD Sum; /* data is shared by the thread(s) */ /* the thread runs in this separate function */ DWORD WINAPI Summation(PVOID Param) DWORD Upper = *(DWORD *)Param; for (DWORD i = 0; i <= Upper; i++) Sum += i; return 0; 4.20 if (Param < 0) fprintf(stderr, "an integer >= 0 is required \n"); return -1; // create the thread ThreadHandle = CreateThread(NULL, 0, Summation, &Param, 0, &ThreadId); if (ThreadHandle!= NULL) WaitForSingleObject(ThreadHandle, INFINITE); CloseHandle(ThreadHandle); printf("sum = %d\n",sum);
Java Threads Java threads are managed by the JVM Java threads may be created by:» Extending Thread class» Implementing the Runnable interface Java Thread 생성 1 Thread class로부터새 class 유도하고 run() 재정의 start() 가 (1) 메모리할당하고새 thread 초기화, (2) run() 실행 절대로직접 run() 호출하지말고 start() 를호출할것! ( 초기화때문 ) 2 Runnable interface를구현하는 class를정의하고새 Thread 객체 주로 class가이미유도된경우이용 ( 예 ) public class ThreadedApplet extends Applet implements Runnable Java는 multiple inheritance 불가 4.21
Thread class 확장으로 thread 생성 class Worker1 extends Thread public void run() System.out.println( I am a Worker Thread ); public class First public static void main(string args[]) Worker runner = new Worker1(); runner.start(); System.out.println( I am the main thread ); 4.22
Runnable interface 를구현하여 thread 생성 public interface Runnable public abstract void run(); /* Runnable interface 코딩않음 */ class Worker2 implements Runnable public void run() System.out.println( I am a Worker Thread ); public class Second public static void main(string args[]) Runnable runner = new Worker2(); Thread thrd = new Thread(runner); thrd.start(); System.out.println( I am the main thread ); 4.23
Java Threads Thread 관리» Java의 thread 관리 APIs suspend() sleep() resume() stop()» multithreading 예 : applet 일반적으로 graphics, animation, audio 등처리 처음 applet 실행될때 start(), display 않는동안 stop() ClockApplet 참조 Thread 상태» New: new 문으로 thread 객체생성» Runnable: start() 호출로메모리할당하고 run() 호출한상태» Blocked: I/O, sleep(), suspend() 로 block된상태» Dead: stop() 호출된상태 4.24
Applet standalone application : 지금까지본자바프로그램들 applet : web page 에삽입되어실행되는자바프로그램» No main()» Constructor: init() AppletViewer FirstApplet.html 로실행 FirstApplet.java 파일 import java.applet.*; import java.awt.*; public class FirstApplet extends Applet public void init() //initialization code goes here FirstApplet.html 파일 <applet Code = FirstApplet.class Width = 400 Height = 200> </applet> public void paint(graphics g) g.drawstring( Java Primer Now Brewing!,15,15); 4.25
날짜와시간을출력하는 ClockApplet import java.applet.* ; import java.awt.* ; public class ClockApplet extends Applet implements Runnable public void run() while(true) try Thread.sleep(1000); catch(interruptedexception e) repaint(); public void start() if(clockthread == null) clockthread = new Thread(this); clockthread.start() ; else clockthread.resume(); resume(); public void stop() if(clockthread!= null) clockthread.suspend() ; public void destroy() if(clockthread!= null) clockthread.stop() ; clockthread = null ; public void paint(graphics g) g.drawstring(new java.util.date().tostring(), 10, 30) ; private Thread clockthread; <applet code = ClockApplet width = 250 height = 50> </applet> 4.26
Java Threads Thread와 JVM» JVM의 system-level threads garbage-collector thread timer events handling thread: sleep() graphics control thread: 버튼입력, 스크린갱신 JVM과호스트 OS» Java threads = user threads» JVM이 Java threads 관리 Windows NT: one-to-one model Solaris 21 2.1~2.5: 25 many-to-one model Solaris 2.6~: many-to-many model Multithreaded 해법예제 : Mailbox(IPC) 를이용하는생산자-소비자문제» The class Server 참조» Producer thread 참조» Consumer thread 참조 4.27
Java Thread States 4.28
Driver.java class Sum private int sum; public int get() return sum; public void set(int sum) this.sum = sum; class Summation implements Runnable private int upper; private Sum sumvalue; public Summation(int upper, Sum sumvalue) if (upper < 0) throw new IllegalArgumentException(); this.upper = upper; this.sumvalue = sumvalue; public void run() int sum = 0; for (int i = 0; i <= upper; i++) sum += i; sumvalue.set(sum); 4.29 public class Driver public static void main(string[] args) if (args.length!= 1) System.err.println("Usage Driver <integer>"); System.exit(0); Sum sumobject = new Sum(); int upper = Integer.parseInt(args[0]); Thread worker = new Thread(new Summation(upper, sumobject)); worker.start(); try worker.join(); catch (InterruptedException t ti ie) ) System.out.println("The sum of " + upper + " is " + sumobject.get());
Threading Issues Semantics of fork() and exec() system calls» Does fork() duplicate only the calling thread or all threads? 목표스레드 (target thread; 취소되어야할스레드 ) 의스레드종료 (Thread cancellation )» 비동기식취소 (Asynchronous cancellation): 즉시목표스레드를강제종료» 지연취소 (Deferred cancellation): 목표스레드가주기적으로강제종료되어야할지를체크 시그널처리 (Signal handling)» A signal handler is used to process signals 디폴트신호처리기 사용자정의신호처리기» 어느스레드에게전달? 신호가적용될스레드에게 모든스레드에게 몇몇스레드에게 특정스레드가전달받도록지정 스레드풀 (Thread pools)» 새스레드를만들기보다기존스레드로서비스하는것이빠름 : Win32API PoolFunction()» 존재할스레드개수에제한을둠 스레드별데이터 (Thread-specific data)» 각스레드가자기자신만의데이터를가짐» 스레드풀사용등스레드를생성할수없을때유리함 스케줄러액티베이션 (Scheduler activations)» 다대다모델 (Many-to-Many models) 과두수준모델 (Two-level models) 은응용에할당할커널스레드를적정수준으로유지하기위한통신필요» 스케줄러액티베이션방법은커널스레드로부터스레드라이브러리로의통신메커니즘 upcalls 지원» LWP = 가상처리기 (virtual processor) 4.30
4 장실습 ~mysung/thread/pthread.c 프로그램과 ~mysung/thread/thread.c 프로그램을코딩하여실행해보세요.» /usr/include/pthread.h 와 /usr/include/thread.h 참조» POSIX http://www.unix.org/version3/sample/functions/abort.html Pthread Summation 프로그램을코딩하여실행해보세요. Windows XP thread (Win32 thread) Summation 프로그램을코딩하여실행해보세요. 자식스레드를만들어자식스레드로하여금리눅스에서는 $ ls -al 을, 윈도우환경에서는 > dir /a 명령을수행시키는프로그램을아래버전으로각각만들어숙제디렉토리에제출하세요.» pthread 버전» Win32 thread 버전 4.31
( 참고 ) Java Threads: Extending the Thread Class class Worker1 extends Thread public void run() System.out.println("I Am a Worker Thread"); public class First public static void main(string args[]) Worker1 runner = new Worker1(); runner.start(); System.out.println("I Am The Main Thread"); 4.32
( 참고 ) Java Threads: The Runnable Interface The Runnable Interface public interface Runnable Implementing the Runnable Interface class Worker2 implements Runnable public void run() public abstract void System.out.println("I Am a Worker Thread "); run(); public class Second public static void main(string args[]) Runnable runner = new Worker2(); Thread thrd = new Thread(runner); thrd.start(); System.out.println("I Am The Main Thread"); 4.33
( 참고 ) Java Threads: Joining Threads class JoinableWorker implements Runnable public void run() System.out.println("Worker working"); public class JoinExample public static void main(string[] args) Thread task = new Thread(new JoinableWorker()); task.start(); try task.join(); catch (InterruptedException ie) System.out.println("Worker done"); 4.34
( 참고 ) Java Threads: Thread Cancellation Thread Cancellation 2 Thread Cancellation 1 public class CancelExample public static void main(string[] args) Thread thrd = new Thread (new InterruptibleThread()); thrd.start(); // now interrupt it thrd.interrupt(); public class InterruptibleThread implements Runnable public void run() while (true) /** * do some work for awhile */ if (Thread.currentThread().isInterrupted()) System.out.println("I'm interrupted!"); break; // clean up and terminate 4.35
( 참고 ) Thread Specific Data Thread Specific Data 1 Thread Specific Data 2 class Service class Worker implements Runnable private static ThreadLocal errorcode = new ThreadLocal(); private static Service provider; public static void transaction() try /** * some operation where an error may occur */ catch (Exception e) errorcode.set(e); public void run() provider.transaction(); System.out.println(provider.getErrorCode()); ()) /** * get the error code for this transaction */ public static Object geterrorcode() return errorcode.get(); 4.36