'Thread'에 해당하는 글 3건

앞선 쓰레드1쓰레드2를 통해서 쓰레드에 관한 내용들을 알아보았는데 이제 쓰레드에 관한 정리도 끝나간다. (앞에 내용을 보지 못하신 분들은 링크를 타고 보실 것을 권함)

이번에는 쓰레드를 사용하면서 동기화란 어떤 것이면 어떻게 사용하는지와 어떻게하면 동기화의 효율을 높일 수 있는지 알아보자.

 

쓰레드의 동기화란?

내가 컴퓨터로 몇시간동안 문서 작업을 하다가 잠시 자리를 비운 사이에 다른 사람이 문서를 만든다고 건드려서 내 작업이 날아가면 어떻게 될까??? (생각만 해도 끔찍...ㅠㅠ!!!)

이럴 때는 문서 작업이 다 끝날 때까지 다른 사람이 컴퓨터를 사용할 수 없게 비밀번호를 설정해서 잠금 상태(lock)로 해놓으면 될 것 같다.

이처럼, 데이터에 lock을 걸어서 먼저 작업 중이던 쓰레드가 작업을 완전히 마칠 때까지는 다른 쓰레드에게 제어권이 넘어가더라도 데이터가 변경되지 않도록 보호함으로써 동기화를 시킬 수 있다.

 

synchronized를 이용한 동기화

자바에서는 키워드 synchronized를 이용해 공유 데이터에 lock을 걸어서 동기화를 가능하게 함.

이때, synchronized는 두 가지 방법으로 사용 됨.

 

· 특정한 객체에 lock을 걸고자 할 때

synchronized(객체의 참조변수) {
	
}

synchronized 블록의 경우, 지정된 객체는 synchronized 블럭의 시작부터 lock이 걸렸다가 블록이 끝나면 lock이 풀림.

이 블록을 수행하는 동안은 지정된 객체에 lock이 걸려서 다른 쓰레드가 이 객체에 접근할 수 없게 됨.

 

· 메서드에 lock을 걸고자 할 때

public synchronized void cal() {
	
}

synchronized 메서드의 경우, 한 쓰레드가 synchronized 메서드를 호출해서 수행하고 있으면 메서드가 종료될 때까지 다른 쓰레드가 이 메서드를 호출할 수 없음.

 

교착상태(dead lock)에 빠질 수 있기때문에 가능하면 메서드에 synchronized를 사용하는 메서드 단위의 동기화를 권장.

 

 

 

쓰레드를 동기화 할때, 한 쓰레드가 객체에 lock을 걸고 어떤 조건이 만족될 때까지 기다려야 하는 경우가 생길 수 있다. 이럴 때, 이 쓰레드를 그대로 놔두면 이 객체를 사용하려는 다른 쓰레드들은 lock이 풀릴 때까지 같이 기다려야만 하는 상황이 발생한다.

이런 비효율을 개선하기 위해서 wait()와 notify() 또는 notifyAll()을 사용하여 동기화의 효율을 높여준다.

wait()

한 쓰레드가 객체에 lock을 걸고 오래 기다리는 대신 wait()을 호출해서 다른 쓰레드에게 제어권을 넘겨주고 대기 상태로 기다림.

Thread 클래스가 아닌 Object 클래스에서 정의된 메서드로 모든 객체에서 호출이 가능.

동기화 블록 내에서만 사용 가능.

 

notify()

대기 상태로 기다리는 쓰레드를 다른 쓰레드에 의해서 notify()가 호출되면 다시 실행상태로 만듬.

Thread 클래스가 아닌 Object 클래스에서 정의된 메서드로 모든 객체에서 호출이 가능.

동기화 블록 내에서만 사용 가능.

 

notify()와 notifyAll()의 차이점

notify()는 waiting pool에 있는 쓰레드 중에서 하나만 깨우고 notifyAll()은 모든 쓰레드를 깨움. 하지만 어차피 한 번에 하나의 쓰레드만 사용 가능하기 때문에 별 차이는 없음.

 

※ notify()를 사용할 경우 어떤 쓰레드가 깨워지게 될지는 알 수 없어서 특정 쓰레드가 오랫동안 waiting pool에 머물 수 있기 때문에 다시 객체의 waiting pool에 들어가게 되더라도 notifyAll()을 이용해서 모든 쓰레드를 깨워놓고 JVM의 쓰레드 스케줄링에 의해서 처리되도록 하는 것이 안전함.

 

 

2017/11/03 - [프로그래밍/Java] - 쓰레드(Thread) 1

2017/11/04 - [프로그래밍/Java] - 쓰레드(Thread) 2

 

 

 

 

'프로그래밍 > Java' 카테고리의 다른 글

enum 2  (3) 2018.01.28
enum 1  (0) 2018.01.02
쓰레드(Thread) 2  (0) 2017.11.04
쓰레드(Thread) 1  (0) 2017.11.03
컬렉션 프레임워크(Collection Framework)란?  (0) 2017.09.01

WRITTEN BY
김치치즈스마일
세계정복!

,

앞서서 쓰레드에 관한 기본적인 내용들을 알아보았다.

이번에는 쓰레드의 세부적인 것을 알아보도록 하자.

 

 

쓰레드의 우선순위

· 쓰레드는 우선순위(priority)라는 것을 가지고 있어서 우선순위의 값에 따라 쓰레드가 얻는 시간을 다르게 줄 수 있음.

· 쓰레드가 가질 수 있는 우선 순위의 범위는 1에서 10까지 이며 높을수록 우선순위가 높은 것. (우선 순위의 높고 낮음은 절대적인 것이 아닌 상대적인 것)

· 쓰레드의 우선순위는 쓰레드를 생성한 쓰레드로부터 상속 받는 것. (main메서드를 수행하는 쓰레드는 우선순위가 5이므로 main 메서드 내에서 생성하는 쓰레드는 자동적으로 우선순위가 5가 됨)

 

void setPriority(int newPriority); // 쓰레드의 우선순위를 지정한 값으로 변경
int getPriority(); // 쓰레드의 우선순위를 반환
		
public static final int MAX_PRIORITY = 10; // 최대 우선순위
public static final int MIN_PRIORITY = 1; // 최소 우선순위
public static final int NORM_PRIORITY = 5; // 보통 우선순위

 

쓰레드의 스케줄링과 관련된 메서드

생성자 / 메서드 

설명 

void interrupt()

sleep()이나 join()에 의해 일시정지인 쓰레드를 실행대기상태로 만듬

해당 쓰레드에서는 interruptedException일 발생하여 일시정지상태를 벗어나게 됨

void join()

void join(long millis)

void join(long millis, ont nanos)

지정된 시간동안 쓰레드가 실행되도록 함

지정된 시간이 지나거나 작업이 종료되면 join()을 호출한 쓰레드로 다시 돌아가 실행을 계속 함 

void resume() 

suspend()에 의해 일시정지해 있는 쓰레드를 실행대기상태로 만듬

교착상태에 빠지기 쉽기 때문에 deprecated됨

static void sleep(long millis)

static void sleep(long millis, int nanos)

지정된 시간동안 쓰레드를 일시정지시킴

지정한 시간이 지나면 자동적으로 다시 실행대기 상태가 됨 

void stop() 

쓰레ㅐ드를 즉시 종료 시킴

교착상태에 빠지기 쉽기 때문에 deprecated됨

void suspend() 

쓰레드를 일시정지시킴

resume()을 호출하면 다시 실행대기상태가 됨

교착상태에 빠지기 쉽기 때문에 deprecated됨

static void yield() 

실행 중에 다른 쓰레드에게 양보하고 실행대기상태가 됨 

 

쓰레드의 상태

상태 

설명 

NEW 

쓰레드가 생성되고 아직 start()가 호출되지 않은 상태

RUNNABLE 

실행 중 또는 실행 가능한 상태 

BLOCKED 

동기화 블럭에 의해서 일시정지된 상태 (lock이 풀릴 때까지 기다리는 상태)

WAITING, TIMED_WAITING 

쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시정지 상태

TIMED_WAITING은 일시정지시간이 지정된 경우를 의미

TERMINATED 

쓰레드의 작업이 종료된 상태

 

 

[참고] 자바의 정석

 

 

2017/11/03 - [프로그래밍/Java] - 쓰레드(Thread) 1

 

'프로그래밍 > Java' 카테고리의 다른 글

enum 1  (0) 2018.01.02
쓰레드(Thread) 3  (0) 2017.11.20
쓰레드(Thread) 1  (0) 2017.11.03
컬렉션 프레임워크(Collection Framework)란?  (0) 2017.09.01
throw와 throws 비교  (0) 2017.08.28

WRITTEN BY
김치치즈스마일
세계정복!

,

 

우리는 채팅창에서 대화를 주고 받으면서 동시에 채팅창에 사진을 올려 공유할 수도 있다. 이처럼 동시에 여러 작업을 할 수 있는 것은 무엇 때문일까? 바로 쓰레드 덕분이다.

그렇다면 쓰레드란 무엇일까? 이제 알아보도록 하자.

 

쓰레드란?

· 프로세스 내에서 자원을 이용하여 작업을 수행하는 것.

· 별도의 호출 스택(call stack)이 있다는 것을 의미.

 

멀티 쓰레딩

· 하나의 프로세스 내에서 여러 쓰레드가 동시에 작업을 수행하는 것.

· 실제로는 한 개의 CPU가 한 번에 한 가지의 작업만 할 수 있기 때문에 아주 짧은 시간 동안 여러 작업을 번갈아 가며 수행함으로써 여러 작업이 동시에 수행되는 것처럼 보이게 하는 것.

 

멀티 쓰레딩의 장점

· CPU의 사용률을 향상 시킴.

· 자원을 보다 효율적으로 사용할 수 있음.

· 사용자에 대한 응답성이 향상됨.

· 작업이 분리되어 코드가 간결해짐.

 

※ 프로세스의 성능이 쓰레드의 개수에 비례하지는 않음.

 

멀티 쓰레딩의 단점

잘못하면 교착상태(Deadlock)의 빠질 수 있음.

 

※ 교착상태란 두 쓰레드가 자원을 점유한 상태에서 서로 다른 쓰레드가 점유한 자원을 사용하려고 기다리느라 실행이 멈춰있는 상태.

 

쓰레드 구현하는 방법

· Thread 클래스를 상속 받는 방법

· Runnable 인터페이스를 구현하는 방법

 

Thread 클래스를 상속 받는 방법

public class MyThread extends Thread{
	@Override
	public void run() {
		// Thread 클래스의 run()을 오버라이딩
	}
}

public class MyThreadTest {
	public static void main(String[] args) {
		MyThread th = new MyThread();
		th.start();
	}
}

 

Runnable 인터페이스를 구현하는 방법

public class MyThread implements Runnable {
	@Override
	public void run() {
		// Runnable 인터페이스의 추상메서드인 run()을 구현
	}
}

public class MyThreadTest {
	public static void main(String[] args) {
		Runnable r = new MyThread();
		Thread th = new Thread(r);
		th.start();
	}
}

※ Runnable 객체와 Thread 객체의 관계는 작업과 일꾼 사이의 관계와 같음. Runnable 객체에 Thread에서 실행시킬 작업이 들어있음.

 

※ 쓰레드를 실행시킬 때 왜 run()이 아닌 start()일까? run()을 호출하는 것은 쓰레드를 실행시키는 것이 아니라 단순히 클래스에 속한 메서드를 호출하는 것이다. 따라서 쓰레드의 작업을 실행하는데는 start()를 사용한다.

 

 

[참고] 자바의 정석

[참고] Head First 자바

'프로그래밍 > Java' 카테고리의 다른 글

쓰레드(Thread) 3  (0) 2017.11.20
쓰레드(Thread) 2  (0) 2017.11.04
컬렉션 프레임워크(Collection Framework)란?  (0) 2017.09.01
throw와 throws 비교  (0) 2017.08.28
에러(error)와 예외(exception)  (0) 2017.08.27

WRITTEN BY
김치치즈스마일
세계정복!

,