假设我有两个线程像这样运行:
- 线程 A 在更新共享图像的像素时执行计算
- 线程 B 定期读取图像并将其复制到屏幕
线程 A 快速执行工作,例如每秒 100 万次更新,所以我怀疑经常在锁/互斥/监视器上锁定和解锁是个坏主意。但是,如果没有锁并且无法建立从线程 A 到线程 B 的先发生关系,那么根据 Java 内存模型(JMM 规范),线程 B 根本不能保证看到 A 对图像的任何更新。
所以我认为最小的解决方案是线程 A 和 B 都在同一个共享锁上定期同步,但在同步块内实际上不执行任何工作 - 这就是使模式非标准和可疑的原因。用半真半伪代码来说明:
class ComputationCanvas extends java.awt.Canvas {
private Object lock = new Object();
private int[] pixels = new int[1000000];
public ComputationCanvas() {
new Thread(this::runThreadA).start();
new Thread(this::runThreadB).start();
}
private void runThreadA() {
while (true) {
for (1000 steps) {
update pixels directly
without synchornization
}
synchronized(lock) {} // Blank
}
}
private void runThreadB() {
while (true) {
Thread.sleep(100);
synchronized(lock) {} // Blank
this.repaint();
}
}
@Override
public void paint(Graphics g) {
g.drawImage(pixels, 0, 0);
}
}
这样添加空同步块是否正确实现了线程A向线程B传输数据的效果?还是有其他我无法想象的解决方案?