2011-04-08 139 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

確實。謝謝:)我是個白癡。我會盡快接受你的回答。 – 2011-04-08 10:36:47