본문 바로가기
JAVA

221031 MultiThread 실습

10.Mutual Exclusion(상호 배제)
=>하나의 스레드가 사용 중인 공유 자원을 다른 스레드가 수정하면 안됨
1)공유 자원을 여러 개의 스레드가 동시에 사용했을 때 문제
=>공유 자원으로 사용할 데이터 클래스

 

 

실습

package java_1031.Multithread;

import java.util.concurrent.locks.ReentrantLock;

//자원을 가지고 연산을 하는 스레드에 사용할 클래스
public class ShareData implements Runnable{
	//연산 결과를 지정할 속성
	private int result;
	//연산에 사용할 인덱스
	private int idx;
	
	//공유 코드 영역을 설정하기 위한 객체
	static final ReentrantLock LOCK = new ReentrantLock();
	

	//result의 getter 메서드
	public int getResult() {
		return result;
	}


	public void run(){
		try {
			for(int i=0;i<10;i++) {
				//자물쇠를 채워서 unlock을 만날때 까지는 이 영역의 자원을 수정할 수 없음
				LOCK.lock();
					idx++;
					Thread.sleep(10);
					result =result+idx;
				LOCK.unlock();
			}

		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
		}

	}


}

static final ReentrantLock LOCK = new ReentrantLock();을 생성하여

lock()메서드와 unlock()메서드 사용

 

main

package java_1031.Multithread;

public class MutexMain {
	public static void main(String[] args) {
		//Runnable 인터페이스로부터 상속받은 클래스
		ShareData shareData = new ShareData();
		//스레드 생성
		Thread th1 = new Thread(shareData);
		th1.start();
		Thread th2 = new Thread(shareData);
		th2.start();
		
		
		try {
			//30초 대기-앞의 작업이 스레드로 동작하기 때문에 작업이 끝날때까지 대기하고 결과를 출력
			//바로찍으면 getResult가 먼저 실행될 수도 있음
			Thread.sleep(3000);//스레드가 아니면 전부 다 돌고 getResult가 나옴. 
			//스레드가 2개면 첫번째 스레드가 돌 때 반복문에서 sleep을 만나면 다른 스레드로 감. 같은 변수를 사용하기 때문에 이상한 결과값이 나옴.
			//해결방법은 간단함. synchronized로 묶어주기만 하면 됨. 단, 다른게 못쓰도록 하는 건 최소화시켜야 함
			//또는 ReentrantLock클래스 이용. 이 방법이 권장됨
			System.out.println(shareData.getResult());
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
		}
		
	}
}
210



synchronized 예 

public void run(){
	try {
		for(int i=0;i<10;i++) {
			synchronized(this) {
			idx++;
			Thread.sleep(10);
			result =result+idx;
			}
		}
	} catch (Exception e) {
		System.out.println(e.getLocalizedMessage());
	}

}

synchronized 없이 실행하면 이상한 결과값 출력.
=>ShareData 인스턴스를 1개만 만들어서 공유하는데 하나의 작업이 완료되기 전에 다른 스레드가 공유 자원을 수정하기 때문에 발생

해결 방법
=>한번에 실행되어야 하는 코드를 가진 영역을 찾고 메서드에 synchronized를 붙이던가 코드 영역을 synchronized(공유 객체){}로 묶어주면 됨.
이렇게 묶어주면 묶인 영역의 코드를 동시에 수정할 수 없음
되도록이면 synchronized 메서드를 만드는 것 보다 블럭을 만드는 것을 권장
메서드를 묶게 되면 영역이 커져서 공유도가 떨어지기 때문





최근에는 위의 방법 말고 main에서 사용한 ReentrantLock이라는 클래스를 이용하는 것을 권장
=>인스턴스를 생성하고 lock이라는 메서드로 공유 영역을 만들고 unlock이라는 메서드로 공유 영역을 해제

'JAVA' 카테고리의 다른 글

221031 Semaphore  (0) 2022.10.31
221031 생산자와 소비자 문제  (0) 2022.10.31
221031 Thread2. Multi Thread  (0) 2022.10.31
221028 Daemon Thread  (0) 2022.10.28
221028 Thread  (0) 2022.10.28