고급자바

ThreadShare-22.03.30

AIN99 2022. 3. 30. 17:03
728x90

스레드에서 데이터를 공통으로 사용하는 방법
   1. 공통으로 사용할 데이터를 클래스로 정의한다.
   2. 공통으로 사용할 클래스의 인스턴스를 만든다.
   3. 이 인스턴스를 각각의 스레드에 넘겨준다.
   4. 각각의 스레드는 이 인스턴스의 참조값을 저장한 변수를 이용하여 공통 데이터를 사용한다.
   
   예) 원주율을 계산하는 스레드가 있고 , 계산된 원주율을 출력하는 스레드가 있다.
     원주율을 계산한 후 이 값을 출력하는 프로그램을 작성하시오 
    (이 때 원주율을 저장하는 객체가 필요하다.)

=>계산한 후 값을 출력해야하므로 계산이 완료되었는지를 공유하면서 실행한다.

public class T14_ThreadShareDataTest {

	public static void main(String[] args) {
		ShareData sd=new ShareData();
		
		CalcPIThread cTh=new CalcPIThread(sd);
		PrintPIThread pTh=new PrintPIThread(sd);
		
		cTh.start();
		pTh.start();
	}

}

원주율 결과를  관리하는 클래스

class ShareData{
	public double result; //원주율이 저장될 변수
	/*
	  volatile => 선언된 변수를 컴파일러의 최적화 대상에서 제외시킨다.
	              즉, 값이 변경되는 즉시 변수에 적용시킨다.
	             다중 스레드에서 하나의 변수가 완벽하게 한번에 작동되도록 보장하는 키워드(일종의 동기화)
	 */
	//원주율 계산이 완료되었는지를 나타내는 변수
	volatile boolean isOk=false;
}
더보기

volatile boolean isOk=false;

volatile:휘발성 ,데이터가 위치되지 않음을 알려줌,

지우고 실행하게 되면 start( )가 되었지만 끝나지 않는다.

why? (스레드는 cpu의 코어에서...)

isOk=false

코어1:계산 코어2:출력 동시에 병렬적으로 수행하기 때문에 캐시메모리에 정보를 미리 가져다가 사용

코어1: isOk=false 코어2: isOk=false

             | (실행)

isOk=true

코어1: isOk=true 코어2: isOk=false  코어2도 true이어야 하는데 너무오래걸려서 false 그래서 volatile가 true가 되도록 도와준다. 최적화 isOk=true가 되면 코어2도 바뀌도록!!!!!

동시성 프로그래밍에서 발생할 수 있는 문제 중 하나인 가시성 문제를 해결하기 위해 사용되는 키워드이다. 가시성 문제는 여러 개의 스레드가 사용됨에 따라, CPU Cache Memory RAM의 데이터가 서로 일치하지 않아 생기는 문제를 의미한다. volatile 키워드를 붙인 공유 자원은 RAM에 직접 읽고 쓰는 작업을 수행할 수 있도록 해준다.

원주율을 계산하는 스레드

class CalcPIThread extends Thread{
	private ShareData sd;
	
	public CalcPIThread(ShareData sd) {
		this.sd=sd;
	}
	
	@Override
	public void run() {
		/*
		 원주율=(1/1-1/3+1/5-1/7+1/9.....) *4;
		        1  -  3  +  5  - 7  +  9 =>분모
		        0     1     2    3     4 =>분모를 2로 나눈 몫
		 */
		
		double sum=0.0;
		for(int i=1; i<=1500000; i+=2) {
			if(((i/2)%2)==0){ //2로 나눈 몫이 짝수이면+
				sum+=(1.0/i);
			}else { //2로 나눈 몫이 홀수이면 -
				sum-=(1.0/i);
			}
		}
		sd.result=sum*4; //계산된 원주율을 공통객체의 멤버 변수에 저장
		sd.isOk=true;    //계산이 완료되었음을 알려줌.
	}
}

계산된 원주율을 출력하는 스레드

class PrintPIThread extends Thread {
	private ShareData sd;

	public PrintPIThread(ShareData sd) {
		
		this.sd = sd;
	}
	@Override
	public void run() {
		while(true) {
			//원주율 계산이 완료되었는지 확인
			if(sd.isOk) {
				break;
			}

		}
		System.out.println();
		System.out.println("계산된 원주율: "+sd.result);
		System.out.println("       PI: "+Math.PI);
	}
	
}

 

=>오차가발생한 이유? 무한대여야 하는데 for문으로 정해진 수만큼만 돌렸으므로                 

728x90