我必须解决作业,这是一个问题: 看看这个程序,运行它然后找到问题然后解决它。
这是该计划:
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而只使用主内存。这个操作需要时间 我不确定我的分析,因此我更愿意问你。