Java - 多线程练习

时间:2014-03-16 00:41:50

标签: java multithreading

我必须解决作业,这是一个问题: 看看这个程序,运行它然后找到问题然后解决它。

这是该计划:

package serie02;

import java.util.ArrayList;

class S2Es1Timer {
    private long startTime = -1;
    private long stopTime = -1;

    final protected void start() {
        startTime = System.currentTimeMillis();
    }

    final protected void stop() {
        stopTime = System.currentTimeMillis();
    }

    final public long getElapsedTime() {
        if (startTime < 0 || stopTime < 0)
            return 0;
        return stopTime - startTime;
    }
}

class S2Es1SharedState {
    boolean sharedState = false;
}

class S2Es1Worker implements Runnable {
    private static final long START_VALUE = 1000000000;
    private final int id;
    private final S2Es1Timer timer;
    private final S2Es1SharedState state;
    private long localCounter = START_VALUE;

    public S2Es1Worker(final int id, final S2Es1SharedState state) {
        this.id = id;
        timer = new S2Es1Timer();
        this.state = state;
        log("created");
    }

    @Override
    public void run() {
        timer.start();

        while (--localCounter > 0) {
            if (state.sharedState) {
                timer.stop();
                log("sharedState has already been set by another worker. localCounter: "
                        + ((100.0 * localCounter) / START_VALUE)
                        + " % from goal");
                return;
            }
        }
        // richiedi accesso esclusivo per scrittura
        state.sharedState = true;

        timer.stop();
        log("sharedState has been set");
    }

    final protected void log(final String s) {
        System.out.println(this.getClass().getSimpleName() + id + ": " + s);
    }

    final protected void logElapseTime() {
        log("time: " + timer.getElapsedTime() + " ms");
    }
}

public class S2Esercizio1 {
    private final static int NUM_WORKERS = 10;

    public static void main(final String[] args) {
        final S2Es1Timer mainTimer = new S2Es1Timer();
        final ArrayList<Thread> threads = new ArrayList<Thread>();
        final ArrayList<S2Es1Worker> workers = new ArrayList<S2Es1Worker>();
        final S2Es1SharedState myShare = new S2Es1SharedState();

        // Crea 10 Workers
        for (int i = 0; i < NUM_WORKERS; i++) {
            final S2Es1Worker worker = new S2Es1Worker(i, myShare);
            workers.add(worker);
            threads.add(new Thread(worker));
        }

        System.out.println("Simulation started");
        System.out.println("------------------------------------");
        mainTimer.start();

        // Fa partire tutte le threads
        for (final Thread t : threads)
            t.start();

        try {
            // Attende che tutte le threads terminano
            for (final Thread t : threads)
                t.join();
        } catch (final InterruptedException e) {
            /* Unhandled exception */
        }
        mainTimer.stop();

        System.out.println("------------------------------------");
        for (final S2Es1Worker worker : workers)
            worker.logElapseTime();
        System.out.println("Simulation time: " + mainTimer.getElapsedTime()
                + " ms");
        System.out.println("Simulation finished");
    }
}


这是输出:

S2Es1Worker0: created
S2Es1Worker1: created
S2Es1Worker2: created
S2Es1Worker3: created
S2Es1Worker4: created
S2Es1Worker5: created
S2Es1Worker6: created
S2Es1Worker7: created
S2Es1Worker8: created
S2Es1Worker9: created
Simulation started
------------------------------------
S2Es1Worker6: sharedState has been set
S2Es1Worker7: sharedState has been set
S2Es1Worker3: sharedState has been set
S2Es1Worker5: sharedState has been set
S2Es1Worker9: sharedState has been set
S2Es1Worker0: sharedState has been set
S2Es1Worker4: sharedState has been set
S2Es1Worker8: sharedState has been set
S2Es1Worker1: sharedState has been set
S2Es1Worker2: sharedState has been set
------------------------------------
S2Es1Worker0: time: 2300 ms
S2Es1Worker1: time: 2401 ms
S2Es1Worker2: time: 2420 ms
S2Es1Worker3: time: 1921 ms
S2Es1Worker4: time: 2332 ms
S2Es1Worker5: time: 2169 ms
S2Es1Worker6: time: 909 ms
S2Es1Worker7: time: 1847 ms
S2Es1Worker8: time: 2305 ms
S2Es1Worker9: time: 2237 ms
Simulation time: 2422 ms
Simulation finished

我认为这是一个可见性问题,我的意思是当第一个线程完成循环并将共享可变变量 sharedState 设置为true时,其他线程继续循环,因为它们具有“脏读” “在缓存cpu中(我有4个cpu) 所以我能做的唯一好处是用密钥volatile设置sharedState变量。
这样每个线程都读取正确的值。我浪费了时间,因为这个值现在被主内存而不是cpu缓存捕获。

另一种解决方案可能是:使用ReentrantReadWriteLock。
因此,类S2Es1SharedState可以这样编写:

class S2Es1SharedState {
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock readLock = lock.readLock(); 
    private final Lock writeLock = lock.writeLock(); 
    boolean sharedState = false;

    public boolean getSharedState() {
        readLock.lock();
        try {
            return sharedState;
        } finally {
            readLock.unlock();
        }
    }
    public void setSharedState() {
        writeLock.lock();
        try {
            this.sharedState = true;
        }
        finally {
            writeLock.unlock(); 
        }       
    }
}

这个解决方案我认为工作,因为锁也提供了正确的可见性,但我认为需要花费很多时间,因为这样在循环内部我不使用缓存cpu而只使用主内存。这个操作需要时间 我不确定我的分析,因此我更愿意问你。

0 个答案:

没有答案