【问题标题】:Random result on more threads in the Replicated Workers ParadigmReplicated Workers Paradigm 中更多线程的随机结果
【发布时间】:2014-11-22 21:06:07
【问题描述】:

我的代码如下:

WorkPool.java

import java.util.LinkedList;

/**
 * Class that implements a work pool based on the model of "replicated workers"
 * Tasks introduced in the work pool are objects of type MRCTask
 *
 */
public class WorkPool {
    int nThreads; //total number of worker threads
    int nWaiting = 0; //number of worker threads blocked waiting for a task
    public boolean ready = false; //problem is finished 

    LinkedList<MRCTask> tasks = new LinkedList<MRCTask>();

    /**
     * Constructor for class WorkPool.
     * @param nThreads - number of worker threads
     */
    public WorkPool(int nThreads) {

        this.nThreads = nThreads;

    }

    /**
     * Function which tries to obtain a task from the work pool
     * If there are not available tasks, the function hangs until
     * a task can be given or until the problem is finished
     * @return A task to solve or null if the problem is finished
     */
    public synchronized MRCTask getWork() {

        if (tasks.size() == 0) { //empty work pool
            nWaiting++;
            /*
             * finish condition:
             * there is no available task in the work pool and no worker
             * is active
             */
            if (nWaiting == nThreads) {
                ready = true;
                /* problem is finished, announcing all workers */
                notifyAll();
                return null;
            } else {
                while (!ready && tasks.size() == 0) {
                    try {
                        this.wait();
                    } catch(Exception e) {e.printStackTrace();}
                }

                if (ready)
                    /* work is done */
                    return null;

                nWaiting--;

            }
        }
        return tasks.remove();

    }

    /**
     * Function which inserts a task in the work pool
     * @param sp The task which must be introduced
     */
    synchronized void putWork(MRCTask sp) {

        tasks.add(sp);
        /* announcing one of the waiting workers */
        this.notify();

    }

}

TestMain.Java

public class TestMain {

public static void main(String[] args) throws InterruptedException {

    int nr_proc = Runtime.getRuntime().availableProcessors();
    WorkPool wp = new WorkPool(nr_proc);
    MRCTask.t = 0;
    for(int i = 0; i < 10000; i++)
        wp.putWork(new MRCTask());

    Worker[] wrk = new Worker[nr_proc];

    for(int i = 0; i < nr_proc; i++)
        wrk[i] = new Worker(wp);

    for(int i = 0; i < nr_proc; i++)
        wrk[i].start();

    for(int i = 0; i < nr_proc; i++)
        wrk[i].join();

    System.out.println(MRCTask.t);
}

}

class Worker extends Thread {

WorkPool wp;

public Worker(WorkPool wp) {

    this.wp = wp;

}

void work(MRCTask ps) throws Exception {

    ps.processTask();

}

public void run() {

    while (true) {
        MRCTask ps = wp.getWork();
        if (ps == null)
            break;          
        try {
            work(ps);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }

}

}

class MRCTask {

static int t;
public void processTask() {
    t += 5;
}

}

运行此代码时,我通常期望得到 50000 作为答案。这只发生在 nr_proc 为 1 时。当 nr_proc 为 2 或 4(在我的情况下,availableProcessor() 返回 4)时,我得到随机值,例如 49960、49900、49995,有时甚至是 50000。 你能告诉我有什么问题吗? 在此先感谢并为这个巨大的代码感到抱歉! PS:我尝试修改函数 processTask() 如下:

public void processTask() {
    synchronized(this) {
        t += 5;
    }
}

但是,我仍然遇到同样的问题。我认为同步部分会有所帮助,但事实并非如此。

【问题讨论】:

    标签: java multithreading concurrency synchronized


    【解决方案1】:

    您的值t 是静态的。因此,您尝试同步事物的方式注定要失败。您实际上没有同步任何内容,因为您有许多不同的 MRCTask 实例(实际上是 10000 个)。他们每个人都有一个单独的锁/监视器。 尝试将MRCTask 中的代码更改为:

    private static final Object LOCK = new Object();
    
    public void processTask() {
        synchronized (LOCK) {
            t += 5;
        }
    
    }
    

    这是不同的,现在您使用共享锁。 看看你是否仍然得到不可预测/随机的结果。你不会的。 以前你只是有一个经典的比赛条件。

    【讨论】:

    • 我已经尝试过了,它成功了!十分感谢!但是,同步(this)何时真正起作用?
    • 如果所有线程都看到this 相同,它实际上会起作用。在这里,您分别有许多 MRCTask 对象和许多 this 值。因此,例如,如果 this 是您的池对象(您只有 1 个池),那么它也可以正常工作。我确保我只有 1 个 LOCK 对象,这就是它也适用于我的版本的原因。
    • 谢谢!现在我开始对java多线程特性有了更好的理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 2018-02-05
    相关资源
    最近更新 更多