java 다중 루틴 (二) 공유 자원 경쟁 해결

[블로그는 자신의 복습을 위해 면접 지식을 정리하고 정리할 준비를 하고 있습니다. 만약 잘못이 있으면 각 지역의 큰 신들이 바로잡아 주셔서 감사합니다!]
1. 문제의 출현
/*
 *          
 * canceled             
 * */
public abstract class IntGenerator {
	private volatile boolean canceled = false;
	public abstract int next();
	public void cancel(){
		canceled = true;
	}
	
	public boolean isCanceled(){
		return canceled;
	}
}
/*
 *        :         ,            【  】
 * test()  :      【    IntGenerator】   
 */
public class EvenChecker implements Runnable {
	private IntGenerator generator;
	private final int id;
	
	public EvenChecker(IntGenerator g, int id){			//          Generator(       )
		generator = g;
		this.id = id;
	}

	@Override
	public void run() {
		while( !generator.isCanceled() ){
			int val = generator.next();
			if(val %2 != 0){
				System.out.println(val + "  not even!");
				generator.cancel();
			}
		}
	}
	//    【    IntGenerator】 EvenChcker
	public static  void test(IntGenerator gp, int count){
		ExecutorService exec = Executors.newCachedThreadPool();
		for(int i = 0; i < count; i++){
			exec.execute(new EvenChecker(gp, i));
		}
		exec.shutdown();
	}
	public static  void test(IntGenerator gp){
		test(gp, 10);
	}
}
//      <span style="font-family:Arial, Helvetica, sans-serif;">Generator                 </span>
// java          ,       ,             
public class EvenGenerator extends IntGenerator {
	private int currentEvenValue = 0;		
	@Override
	public int next() {			
		++currentEvenValue;			//                   
		Thread.yield();
		++currentEvenValue;
		//currentEvenValue += 2;
		return currentEvenValue;
	}
	
	public static void main(String[] args) {
		EvenGenerator eg = new EvenGenerator();
		EvenChecker.test(eg);
	}

}
2.키워드synchronized를 사용하여 문제 해결
만약synchronized로 표시된 방법에 대한 작업이 호출되고 있다면, 이 작업이 이 방법에서 되돌아오기 전에, 이 클래스에 표시된synchronized로 표시된 방법의 모든 호출이 막힐 것이다. 즉,
특정한 대상에 대해 그 모든synchronized 방법은 같은 자물쇠를 공유한다.
상례의 세 번째 단락 코드를 다음과 같이 바꾸면 프로그램은 영원히 정상 상태에 있고 끊임없이 짝수를 출력할 것이다
/*
 * 1.synchronized         ,        
 * 2.        ,   synchronized         
 * 3.    :synchronized              private ,            
 * 4.              
 */
public class EvenGenerator extends IntGenerator {
	
	private int currentEvenValue = 0;		//          private   ,               

	@Override
	public synchronized int next() {			//  synchronized           ,yield()      
		++currentEvenValue;			//                   
		Thread.yield();
		++currentEvenValue;
		//currentEvenValue += 2;
		return currentEvenValue;
	}
	
	public static void main(String[] args) {
		EvenGenerator eg = new EvenGenerator();
		EvenChecker.test(eg);
	}

}

2. 표시된 Lock 객체를 사용하여 문제 해결
/*
 * synchronized    EvenGenerator
 * 1.Locks          、     
 * */
public class LockedEventGenerator extends IntGenerator{
	
	private int currentEvenValue = 0;
	
	private Lock lock = new ReentrantLock();		//   

	@Override
	public int next() {
		lock.lock();  			//  
		try{
			++currentEvenValue;
			Thread.yield();
			++currentEvenValue;
			return currentEvenValue;
		}finally{
			lock.unlock(); 		//  
		}
	}
	
	public static void main(String[] args) {
		EvenChecker.test(new LockedEventGenerator());
	}
}

3.원자성
원자 조작은 라인 스케줄링 메커니즘에 의해 중단될 수 없는 조작을 가리킨다.
원자성은 더블과 롱을 제외한 모든 기본 유형의 읽기와 쓰기 작업에 적용될 수 있다
volatile 키워드로 롱이나 더블 유형의 변수를 수식할 때 원자성을 얻고,
비록 이것은synchronized와 유사한 효과가 발생할 수 있지만, 우리는volatile 키워드를 사용하는 것을 최대한 피하고synchronized로 전환해야 한다

좋은 웹페이지 즐겨찾기