2017-11-25 1 views
0

멀티 스레딩에서 레이스 조건을 수행하고 경쟁 조건을 야기하는 상황을 만들려고 생각했지만 동일한 결과를 얻을 때마다 간단한 프로그램을 작성했습니다. 이것이 레이스 컨디션의 올바른 상황인지 알아야합니다. 아래자바 멀티 스레딩 레이스 조건 시나리오

코드 :

package com.threads; 

/** 
* demonstrate race conditions 
*/ 

public class Step4 { 

public int getA() { 
    return a; 
} 

public void addToA(int number) { 

    for(int i=0;i<number;i++) 
     this.a = this.a + 1; 
} 

int a = 2; 
static Step4 s4 = new Step4(); 

public static void main(String[] args) throws InterruptedException { 
    Thread thread1 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(5); 
     } 
    }); 

    Thread thread2 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(3); 
     } 
    }); 

    Thread thread3 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(6); 
     } 
    }); 

    Thread thread4 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(4); 
     } 
    }); 


    thread1.start();  
    thread2.start();  
    thread3.start(); 
    thread4.start(); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 
    thread4.join(); 

    System.out.println(s4.getA()); 

} 

} 

// 출력은 내 컴퓨터, Win7에 32 비트에서 항상 20입니다.

+3

각 스레드가 여기에서 거의 작동하지 않아서 전혀 겹치지 않을 가능성이 매우 높습니다. –

+0

4 개의 스레드가 모두 완료 될 때까지 기다리는 중입니다 (join() 메서드). ** println **이 호출되면 내용은 항상 20입니다. 따라서 경쟁 조건을 시뮬레이트하지 않습니다. –

+2

숫자를 훨씬 더 크게 만드십시오. 경쟁 조건은 예측할 수 없으므로 각 스레드가 더 많은 시간을 소비하게되면 발생 가능성이 높아집니다. – Kiskae

답변

0

모든 스레드가 필드에 추가하기 때문에 프로그램의 레이스 상태가 매우 낮을 수 있으므로 순서가 최종 결과에 영향을줍니다. 두 스레드가 동일한 값인 으로 읽은 경우에만 새 값을 할당 한 다음 두 번째 스레드가 새 값을 할당하면 증분이 "손실"될 수 있습니다.

public class Step4 { 

    public int getA() { 
    return a; 
    } 

    public void addToA(int number) { 
    try { 
     Thread.sleep(100); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    for(int i=0;i<number;i++) 
     this.a = this.a + 1; 
    } 

    public void multiplyA(int number) { 
    try { 
     Thread.sleep(100); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    this.a = this.a * number; 
    } 

    int a = 2; 
    static Step4 s4; 

    public static void main(String[] args) throws InterruptedException { 

    for (int i = 0; i < 10; i++) { 
     s4 = new Step4(); 
     doRun(); 
     System.out.println("*******"); 
    } 
    } 

    private static void doRun() throws InterruptedException { 
    Thread thread1 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(5); 
     } 
    }); 

    Thread thread2 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.multiplyA(3); 
     } 
    }); 

    Thread thread3 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(6); 
     } 
    }); 

    Thread thread4 = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      s4.addToA(4); 
     } 
    }); 


    thread1.start(); 
    thread2.start(); 
    thread3.start(); 
    thread4.start(); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 
    thread4.join(); 

    System.out.println(s4.getA()); 

    } 

} 

내가 다른 결과를 얻을 수있는 기회를 높이기 위해, 100 MS는 모두 행동에 잠을 추가했습니다 : 여기

더 자주 경쟁 조건을 앓고 수정 된 버전입니다. 대부분의 경우 결과는 31이지만 다른 시간대에는 17, 21 또는 51 일 수 있습니다.

+1

경쟁 조건이 있습니다. 두 개의 쓰레드는 a의 현재 값을 병렬로 읽고 그 값을 증가시킬 수 있기 때문에 증가분은 잃어 버리게된다. –

+0

@JBNizet, 네 그것은 사실입니다. 나는 대답을 편집했다. –

0

코드에 읽기 및 쓰기가 포함되므로 경쟁 조건을 시뮬레이트합니다. 그러나 실제로 여기에서 경주를 보여주기 위해서는 모든 스레드가 추가이기 때문에 꽤 불행한 일정이 필요합니다. 다른 시스템에서이 작업을 실행하거나 일부 스레드가 디비전 또는 뺄셈과 같은 다른 작업을 수행하도록 할 수 있습니다.

또 다른 옵션은 Thread.sleep(random)addTo()에 추가하여 경쟁 조건을 보장하는 것입니다.