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