자바

2017-10-19 5 views
-1

에서 내 자신의 세마포어 내가 자바 내 자신 세마포어를 구현하고 싶습니다 내가 그런 식으로 구현 한 (단지 연습, 나는 세마포 클래스가 있다는 것을, 알고) 내가 시작자바

public class MyThread extends Thread { 

    private static MySemaphore semaphore = new MySemaphore(); 
    public void run(){ 
     for (int i = 0; i < 100; i++) { 

      semaphore.take(); 
      try { 
       Main.myVariable += 1; 
       semaphore.release(); 
      } catch (Exception e){ 
       System.out.println("Exception" + e.getMessage()); 
      } 
     } 
    } 
} 

와 같은 스레드에 가입 :

import java.util.ArrayList; 
import java.util.List; 

public class Main { 

    public static int myVariable = 0; 

    private static int threadsNumber = 100; 

    public static void main(String[] args) { 
     List<Thread> allThreads = new ArrayList<>(); 

     for (int i = 0; i < threadsNumber; i++) { 
      allThreads.add(new Thread(new MyThread())); 
     } 

     for (int i = 0; i < threadsNumber; i++) { 
      allThreads.get(i).start(); 
     } 

     for (int i = 0; i < threadsNumber; i++) { 
      try{ 
       allThreads.get(i).join(); 
      } catch (Exception e){ 
       System.out.println(e.getMessage()); 
       System.out.println("********************************"); 
      } 
     } 

     System.out.println("Result is " + myVariable); 

    } 
} 

나는 같은 스레드에서 사용하는 것을 시도하고있다 변수를 10000 번 증분하여 결과를 얻고 싶을뿐입니다. 세마포어가 없으면 결과는 10000 미만 (예 : 9923, 9684)으로 증분이 아닌 원 자성으로 인해 발생합니다. 세마포어를 사용하여이 변수를 보호하고 싶습니다.
불행히도 결과는 여전히 10000보다 작거나 같습니다 (그러나 9990보다 큰 10 개의 사례 중 9 개에 훨씬 가깝습니다). 이유가 궁금하십니까? 내 세마포어가 잘못되었거나 스레드를 시작하는 데 문제가 있습니까?

+4

당신이'take'을 얻었다과'가 혼합 release' 것으로 보인다. 'take' (첫 번째 작업)는 기다려야 만합니다. release는 반드시 알려야합니다. – JimmyB

+0

네가 맞아, 메소드 이름을 바꿔서 제대로 작동했지만, 방금 좋은 방법을 가졌지 만 잘못된 이름을 사용했다. (그 다음에 나오는 것은 부적절하게 사용했다.) 고마워. – Dawid

+0

'AtomicInteger'를 사용해 보았습니까? – diginoise

답변

-1

MySemaphore 클래스에서 값은 이미 1로 설정되어 있습니다. 릴리스 함수에서 값이 0인지 확인하기 때문에 0이어야합니다. 즉, 프로그램을 시작할 때 세마포어를 가질 수있는 스레드가 없습니다 (1로 설정했기 때문에). 그렇게하면 대기 상태가됩니다. 'threadsNumber'가 한계에 도달하면 프로그램이 종료됩니다. 즉, 프로그램이 종료되기 전에 대기 상태에있는 스레드가 있는지 확인하지 않습니다. 왜 성공률이 9/10인지 설명합니다.

내 값을 0으로 설정하고 대기중인 상태의 스레드가 있는지 확인하는 것이 좋습니다.

코드는 다음처럼 :

public class MySemaphore { 
    private int value = 0; //this is already an error in your code 

    public synchronized void take() { 
    this.value++; 
    this.notify(); // wakes up the first thread that called wait on the shared variable 
    } 

    public synchronized void release() throws InterruptedException{ 
    while(this.signals == 0) wait(); 
    this.value--; 
    } 

} 
+1

'synchronized' 블록 외부에서'wait()'/'notify()'를 사용해보십시오. 결과를보고하십시오. – lukeg

+1

세마포어 메서드가 수행하는 작업이 원자 적이지 않기 때문에 synchronized를 사용하고 있습니다. – Dawid

+0

단순히 synchronized 키워드를 사용할 수있을 때 자신의 세마포를 구현하는 요점은 무엇입니까? –