Java同步帮助请求

标签 java multithreading synchronization

我正在为我的应用程序实现一个网络线程管理器。我创建了一个JUnit测试,通过调用以下两个方法快速请求和释放网络线程索引:

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();
        }
    }
}

最佳答案

The only used global variable is already synchronized, isn't it?

没有。

第一个方法是在该方法的封闭类的 Class 对象上进行同步。

第二种方法是在 currThreads 对象上进行同步。

将第一种方法更改为以下方法,应该可以解决这两种方法的同步问题。

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

关于Java同步帮助请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5593786/

相关文章:

java - 回收 ImageViews 以避免 OutOfMemoryError

multithreading - 当事件模式不适用时,线程应该休眠多长时间?

c++ - 无法使用 pthread_kill 和 sigwait 解锁/"wake up"线程

c++ - 对象间共享数据的线程安全访问

java - 安卓 : stopping a thread that sends data to a server

sql-server - access和sql server实时同步

PHP:如何使用 php 代码在不使用 CLI 的情况下在 s3 存储桶之间同步数据。?

java - Spring Thymeleaf 中枚举的本地化

java - PaintComponent() 被调用 200 次

java - 简单的 Java 服务器监听客户端并重定向 [302] 到其他站点