【问题标题】:Safe to update separate regions of a BufferedImage in separate threads?在单独的线程中更新 BufferedImage 的单独区域是否安全?
【发布时间】:2010-05-18 12:47:31
【问题描述】:

我有一组BufferedImage 实例、一个主图像和一些通过在主图像上调用getSubImage 创建的子图像。子图像不重叠。我也在对子图像进行修改,我想将其拆分为多个线程,每个子图像一个。

根据我对BufferedImageRasterDataBuffer 工作原理的理解,这应该是安全的,因为:

  • BufferedImage(及其各自的WritableRasterSampleModel)的每个实例只能从一个线程访问。
  • 共享的ColorModel 是不可变的
  • DataBuffer 没有可以修改的字段(唯一可以更改的是支持数组的元素。)
  • 在单独的线程中修改数组的不相交段是安全的。

但是,我在文档中找不到任何说明这样做绝对安全的内容。我可以假设它是安全的吗?我知道可以处理子 Rasters 的副本,但由于内存限制,我宁愿避免这样做。

否则,是否可以在不复制父图像区域的情况下使操作线程安全?

【问题讨论】:

    标签: java multithreading thread-safety bufferedimage


    【解决方案1】:

    您是否考虑过使用 JAI 将您的“子图像”作为图块进行管理?如果您不必挂在原始图像 BufferedImage 实例及其所有 subImage BufferedImage 实例上,这似乎是对资源的更好利用。关于 JAI 的信息可以在这里找到: JAI README

    有一个类 TiledImage,它实现了 RenderedImage 接口(给它一个与 BufferedImage 共同的祖先)。根据 JAI 文档:

    平铺的使用还有助于 使用多个线程 计算。先前分配 瓷砖也可以重复使用以节省 记忆。

    无论如何,使用 RenderedImage 的这些实现之一通常比使用 BufferedImage 更可取,因为 BufferedImage 在内存中维护整个图像的图像快照。 JAI 使用渲染链,可以根据需要回收切片以适应内存限制。

    【讨论】:

      【解决方案2】:

      这是一个很好的分析,对我来说听起来是正确的。没有共享数据,所以并发访问应该没问题。但是,您需要某种保证来确定,而不是有根据的猜测它应该起作用。即使您发现“BufferedImage 旨在同时使用”的声明 - 也不能保证在实践中就是这种情况。

      为了尽可能确定,您可以使用ConTest 编写并发单元测试。并发测试工具检测您的代码并注入人为诱导的上下文切换以暴露并发错误。这将测试 BufferedImage 代码和您自己的代码,因此您可以高度确信它是线程安全的。

      【讨论】:

        【解决方案3】:

        我还没有发现BufferedImage 的线程安全的任何明确证据,但您可能可以通过以下方式解决您的问题:

        不要让不同的工作人员同时处理子图像,而是尝试以每个工作人员消耗同一图像的不同子图像的方式处理许多图像。同一个工作人员将按顺序处理同一图像的子图像。

        您的工作人员会很忙,直到图像数量少于剩余的工作人员。

        还原这个问题:

        W1 W2 W3 Img1 |-------|-------|--------| W1 W2 W3 Img2 |-------|--------|--------| 到: W1 W1 W1 Img1 |-------|-------|--------| W2 W2 W2 Img2 |-------|--------|--------|

        【讨论】:

        • 那么分割图像没有任何优势。
        • 我希望继续在多个线程中处理单个图像的子图像以降低延迟。即使事实证明它需要复制子图像。
        【解决方案4】:

        如果这些答案都不能满足(足够)你可以做一些事情,最终以沉重的(?)价格解决问题。

        Examine the source for BufferedImage, DataBuffer, Raster, etc.这是唯一的办法。

        【讨论】:

        • 我已经这样做了,但是在一种实现上安全并不一定意味着在另一种实现上也是安全的。
        猜你喜欢
        • 2011-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-31
        • 1970-01-01
        • 2012-07-08
        相关资源
        最近更新 更多