我正在尝试 Java 中的多线程,更具体地说,是线程池。作为测试,我编写了一个应用程序,该应用程序仅使用多线程来更改图像的颜色以提高速度。然而,由于某种我不知道的原因,根据我如何设置此测试,我得到的结果已损坏。下面我将描述测试应用程序如何与完整的源代码一起工作。
非常欢迎任何帮助!谢谢你!
测试应用
我有一个 400x300 像素的图像缓冲区,用深蓝色初始化,如下所示:
程序必须用红色完全填充它。
尽管我可以简单地循环所有像素,并按顺序将每个像素着色为红色,但为了提高性能,我决定利用并行性。因此,我决定用单独的线程填充每个图像行。由于行数(300 行)比可用 CPU 核心数大得多,因此我创建了一个线程池(包含 4 个线程),它将消耗 300 个任务(每个任务负责填充一行)。
该计划的组织如下:
RGB 类:将像素颜色保存在双精度数 3 元组中。
RenderTask 类:用红色填充图像缓冲区的给定行。
渲染器类:
创建图像缓冲区。
使用“newFixedThreadPool”创建线程池。
创建 300 个任务供线程池使用。
完成线程池服务。
将图像缓冲区写入 PPM 文件。
一切似乎都适用于该代码,并且我得到了预期的红色图像缓冲区,如下所示:
问题
但是,如果我修改 RenderTask.run() 方法,使其按顺序多次重复设置同一缓冲区位置的颜色,如下所示(我将其称为Version 2):
@Override
public void run() {
for(int column = 0; column < row_width; ++column) {
for(int s = 0; s < 256; ++s) {
image_buffer[current_row][column] = new RGB(1.0, 0.0, 0.0);
}
}
}
然后我得到以下损坏的图像缓冲区:
实际上,每次运行程序的结果都不同,但总是损坏。
据我了解,没有两个线程同时写入同一内存位置,因此似乎没有出现竞争情况。
即使在我认为不会发生的“错误共享”的情况下,我也期望只会降低性能,而不是损坏结果。
因此,即使有冗余的分配,我也希望得到正确的结果(即完全红色的图像缓冲区)。
所以,我的问题是:如果程序的版本 2 与版本 1 的唯一区别是赋值操作在线程范围内冗余执行,为什么会发生这种情况?
是否会出现某些线程在完成之前就被销毁的情况?这会是 JVM 中的错误吗?或者我错过了一些微不足道的事情?(最有力的假设:)
感谢你们!!
撒科打诨
宝慕林4294392
相关分类