Race Condition(2)

28365 ワード

Race Conditionを防ぐ方法はいろいろあります.
前回の記事では、JavaでPetersonアルゴリズムを使用しました.
CはMutex LocksSemaphoreをサポートする.
しかし、高度な言語javaは、より簡単なMonitorsをサポートしています.

Monitorって何?



synchronizedキーワードとは?
  • の臨界領域に対応するコードブロックを宣言するJavaキーワード
  • コードブロック
  • にアクセスするには、ディスプレイロックが必要です.
  • モニタロックを持つオブジェクトインスタンス
  • を指定できます.
  • メソッドで宣言すると、メソッドコードブロック全体が臨界領域として指定されます.
  • のモニタロックを有するオブジェクトインスタンスは、このオブジェクトインスタンス
  • である.
    コードで理解してみましょう.
  • メソッドの一部のみを同期する場合、
  • 	
    	static class Counter {
    		private static Object object = new Object();
    		public static int count = 0;
    		public static void increment() { 
    		// code~~	
    			synchronized(object) {  // 이부분만 임계영역으로 설정해서 메소드 전체가 안돌아가지 않도록 방지!
    			count++;
    			}
    		//code~~
    		}
    	}  
    
    	
    	static class MyRunnable implements Runnable{
    		@Override
    		public void run() {
    			for (int i = 0; i < 10000; i ++) Counter.increment();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception{
    		Thread[] threads = new Thread[5];
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i] = new Thread(new MyRunnable());
    			threads[i].start();
    		}
    		
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i].join();
    		}
    		System.out.println("counter = " + Counter.count);
    	}
    }
  • メソッド自体が結合する場合、
  • // race condition을 monitor rock을 통해 jvm이 알아서 함
    public class SynchExample {
    	static class Counter {
    		public static int count = 0;
    		synchronized public static void increment() { // 메소드 자체를 임계영역으로 묶어 버림
    			count++;
    		}
    	}
    		
    	static class MyRunnable implements Runnable{
    		@Override
    		public void run() {
    			for (int i = 0; i < 10000; i ++) Counter.increment();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception{
    		Thread[] threads = new Thread[5];
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i] = new Thread(new MyRunnable());
    			threads[i].start();
    		}
    		
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i].join();
    		}
    		System.out.println("counter = " + Counter.count);
    	}
    }
    
    エラーコード
    //객체마다 monitor가 다 따로 있음!!!
    public class SynchExample4 {
    	static class Counter {
    		public static int count = 0;
    		public void increment() { 
    			synchronized(this) {  // 이부분만 임계영역으로 설정해서 메소드 전체가 안돌아가지 않도록 방지!
    			Counter.count ++;
    			}
    		//code~~
    		}
    	}  
    
    	 
    	static class MyRunnable implements Runnable{
    		Counter counter;
    		public MyRunnable(Counter counter) {
    			this.counter = counter;
    		}
    		@Override
    		public void run() {
    			for (int i = 0; i < 10000; i ++) counter.increment();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception{
    		Thread[] threads = new Thread[5];
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i] = new Thread(new MyRunnable(new Counter())); 
    			threads[i].start();
    		}
    		
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i].join();
    		}
    		System.out.println("counter = " + Counter.count);
    	}
    }
    各オブジェクトにモニタがあるため、5つのThreadオブジェクトが作成されています.
    全部で5つのディスプレイが...だから普通の価格はありません.
    オブジェクトに置換されたコード
    
    public class SynchExample5 {
    	static class Counter {
    		public static int count = 0;
    		public void increment() { 
    			synchronized(this) {  // 이부분만 임계영역으로 설정해서 메소드 전체가 안돌아가지 않도록 방지!
    			Counter.count ++;
    			}
    		//code~~
    		}
    	}  
    
    	 
    	static class MyRunnable implements Runnable{
    		Counter counter;
    		public MyRunnable(Counter counter) {
    			this.counter = counter;
    		}
    		@Override
    		public void run() {
    			for (int i = 0; i < 10000; i ++) counter.increment();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception{
    		Thread[] threads = new Thread[5];
    		Counter counter = new Counter();
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i] = new Thread(new MyRunnable(counter)); 
    			threads[i].start();
    		}
    		
    		for(int i = 0; i < threads.length; i ++) {
    			threads[i].join();
    		}
    		System.out.println("counter = " + Counter.count);
    	}
    
    }