[JAVA] Process & Thread

GONG PYUNG·2022년 5월 18일
0

1. Overview


1) Process : 운영체제가 바라보는 일의 단위
2) Thread : Process 내에서 다시 나누어지는 일의 단위


2. Context Switch (문맥교환)

  • 실행하고 있는 프로그램 혹은 Process를 교환하는 것
  • 실행에 이용되는 프로그램 카운터, 스택포인터, 레지스터 등의 내용을 넣어두고, 거기까지 실행해 간 Process 등의 실행에 필요한 정보를 보존하여 다음 실행을 시작하는 Process 등의 정보를 이용할 수 있게 하는 조작

    Context Switch을 하는 이유는?
    → 프로세스 수행 중 I/O 이벤트가 발생해 waiting 상태로 전환시키는 경우, CPU가 아무런 일을 하지 않아 발생하는 낭비보다 overhead가 발생하더라도 Context Switching을 통해 다른 프로세스를 실행시키는 것이 더 효율적이기 때문이다.


3. 메모리 공간에서의 Thread

각각의 Process가 독립적인 stack, heap, code, data 영역을 가진 반면에, 한 Process에 속한 Thread는 stack 영역을 제외한 메모리 영역은 공유한다.
Thread는 data, heap 영역을 공유하기 때문에 IPC 없이도 Thread 간의 통신이 가능하다.
Thread는 공유하고 있는 메모리 영역 덕분에 Context Switch로 발생하는 오버헤드(overhead)가 Process에 비해 작다.


4. Thread의 장단점

[장점]

  • 응답성 향상
    응용 프로그램의 일부분이 봉쇄 되거나 긴 작업을 수행하는 경우에도 프로그램의 수행이 계속 되는 것을 허용 함으로써 사용자에 대한 응답성을 증가 시킨다.
    Ex) 이미지 로딩 시 사용자 입력 처리

  • 손쉬운 자원 공유
    Thread는 자동적으로 그들이 속한 Process의 자원들과 메모리를 공유한다.

  • 경제성
    Process 생성을 위해 메모리와 자원을 할당하는 것은 비용이 많이 든다. Thread는 자신이 속한 Process의 자원들을 공유하기 때문에 Thread를 생성하고, Thread간 문맥 교환하는 것이 더 경제적이다.

[단점]

  • 안정성
    멀티 Process는 하나의 Process에서 문제가 발생해도 다른 Process에 영향을 거의 미치지 않지만, 멀티 Thread는 하나의 Process에서 실행되기 때문에, 특정 Thread에서 발생한 문제가 다른 Thread까지 영향을 끼칠 수 있다.

  • 동기화 이슈
    공유 자원에 Thread가 동시에 접근하여 연산을 일으키는 경우에는 잘못된 연산 가능하므로, Thread 간에 동기화가 필요하다.

  • 난해한 프로그래밍 기술
    멀티 Process 방식에 비해서 코드의 흐름을 이해하고 결과를 예측하기 까다롭다.
    문제 발생 시 어떤 Thread에서 문제가 발생했는 지 확인하기 어렵다.


5. Thread 샘플코드

5.1 Thread class 상속

package Process_Thread;

class ThreadClass extends Thread {
	// Thread가 실행되면 run() 호출
	public void run() {
		System.out.println("Thread is started");
		try {
			// join()을 호출하는 Thread는 무한히 기다려 응답없는 상태가 될 수도 있음.
			// 그래서 sleep을 통해 일정 시간 기다린 후 종료되지 않았을 때 빠져나와 다른 작업을 진행함.
			Thread.sleep(10000); // 단위 : ms
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Thread is exiting");
	}
}
public class Thread_Extends {
	public static void main(String[] args) {
		ThreadClass tc1 = new ThreadClass();
		// main과 ThreadClass라는 두개의 쓰레드가 동시에 실행
		tc1.start();
		try {
			// ThreadClass가 종료될 때까지 기다린다.
			tc1.join();
			// 무한히 기다리므로 
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

5.2 Runnable Interface 사용

package Process_Thread;

class ThreadClass2 implements Runnable {
	public void run() {
		System.out.println("Thread is running.......");
	}
}

public class Thread_Implements {

	public static void main(String[] args) {
		ThreadClass2 m1 = new ThreadClass2();
		Thread t1 = new Thread(m1);
		t1.start();
	}
}

5.3 etc..

package Process_Thread;

public class Thread_Sample {

	public static void main(String[] args) {
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + " is running.....");
			}
		});
		
		t1.start();
		
		Runnable taskR = () -> {
			System.out.println(Thread.currentThread().getName() + " is running");
		};
		new Thread(taskR).start();
		
		new Thread(() -> {
			System.out.println(Thread.currentThread().getName() + " is running");
		}).start();
	}
}

실습

문제1) Thread 2개를 만든 후, Main함수와 Thread 2개에서 동시에 0부터 9까지 출력하시오.
어디서 출력하였는지 구분할 수 있게 숫자 앞에 [Main], [Thread1], [Thread2] 표시하시오.

소스 : https://github.com/gongpyung/sysol/blob/master/src/Process_Thread/Thread_Practice1.java

문제2) NUM.TXT에 저장되어 있는 5쌍의 숫자들을 add_2sec.exe.를 통해 덧셈을 실행시킨 후, 각각의 결과들을 모두 출력하시오.

소스 : https://github.com/gongpyung/sysol/blob/master/src/Process_Thread/Thread_Practice2.java

profile
주니어 개발자 공평

0개의 댓글