2011-04-08 5 views
0

내 응용 프로그램 용 네트워크 스레드 관리자를 구현 중입니다. 나는 신속하게 요청하고 다음 두 가지 방법 호출하여 네트워크 스레드 지수를 발표 JUnit 테스트, 만든 : 스레드가 작업을 완료 한 후Java 동기화 도움말 요청

protected static final List <Integer> currThreads   = new ArrayList <Integer>(); 
protected static int     maxThreads   = 5; 
protected static int     lastGrantedId  = 0; 

public static synchronized int reqNewThread(){ 
    if (currThreads.size() >= maxThreads) return -1; 
    ++lastGrantedId; 
    currThreads.add(lastGrantedId); 
    return lastGrantedId; 
} 

public static void threadFinished(final int threadId) throws InternalError{ 
    if (threadId == -1) return; 
    synchronized (currThreads) { 
     boolean works = currThreads.remove(Integer.valueOf(threadId)); 
     assert works : ("threadId: " + threadId); 
    } 
} 

currThreads가 비어 있지 않습니다 만, reqNewThreadthreadFinished 같은 호출 수를 가지고 remove()은 항상 true입니다. 전체 threadFinished 메서드를 동기화하면 올바르게 작동합니다. 질문은 - 왜? 유일하게 사용 된 전역 변수는 이미 동기화 되었습니까? 아닙니다.

JUnit4 테스트 코드 :

final int iters = 15; 
final Runnable getAndFree = new GetAndFree(iters); 
final int sz = 15; 
final Thread[] t = new Thread[sz]; 
for (int i = 0; i < sz; i++) 
    t[i] = new Thread(getAndFree); 
for (int i = 0; i < sz; i++) 
    t[i].start(); 
for (int i = 0; i < sz; i++) 
    t[i].join(); 
assertEquals(0, currThreads.size()); 

테스터 스레드 소스 :

private class GetAndFree implements Runnable { 
    int iters; 

    public GetAndFree(int iters){ 
     this.iters = iters; 
    } 

    @Override 
    public void run(){ 
     try { 
      int id = -1; 
      for (int i = 0; i < iters; i++) { 
       while ((id = reqNewThread()) == -1) { 
        Thread.sleep(25); 
       }; 
       System.out.println("Strarted: " + id); 
       Thread.sleep((long)(Math.random() * 10)); 
       threadFinished(id); 
       System.out.println("Finished: " + id); 
      } // for 
     } catch(final Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

답변

3

이미 동기화 만 사용되는 전역 변수, 그렇지?

첫 번째 방법에있어서의 바깥 Class 클래스의 오브젝트에 동기화된다.

두 번째 방법은 currThreads 개체에서 동기화하는 것입니다.

첫 번째 방법을 다음과 같이 변경하면이 두 가지 방법과 관련하여 동기화 문제가 해결됩니다.

public static int reqNewThread(){ 
    synchronize(currThread) { 
     if (currThreads.size() >= maxThreads) return -1; 
     ++lastGrantedId; 
     currThreads.add(lastGrantedId); 
     return lastGrantedId; 
    } 
} 
+0

실제로. 고마워. :) 나는 바보 야. 가능한 빨리 답변 해 드리겠습니다. –