1

I have a background thread that produces pixels of an image (suppose a java.awt.image.BufferedImage) in a top-down left-right fashion and I want the Swing gui to paint the available portion of the image at regular intervals, to show progress to the user. As far as I undertood from many answers, BufferedImage is not thread-safe so I'm wondering if it's possible to use a java.util.concurrent.Semaphore to enforce synchronization and memory consistency. The background thread would call release() on the semaphore after every pixel write operation while a javax.swing.Timer would call drainPermits() on the semaphore and request the returned number of pixels to be painted. I guess this scheme should work because the documentation of Semaphore states that:

Actions in a thread prior to calling a "release" method such as release() happen-before actions following a successful "acquire" method such as acquire() in another thread.

Please tell me if I am correct.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
maurizeio
  • 266
  • 2
  • 11

1 Answers1

1

As an alternative to java.util.concurrent.Semaphore, consider using a javax.swing.Timer in the model to periodically notify the observing view, and synchronize access to the evolving BufferedImage. If your model is Observable, you can use the optional arg in notifyObservers() to pass boundary information. A complete example is examined here.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I can't understand why in the example posted some of the accesses to the `BufferedImage` are synchronized while others are not. See the `next()` method in class `Model` and the `paintComponent(Graphics)` method in class `View`. – maurizeio Oct 25 '13 at 11:51
  • Good question: `next()` is invoked _only_ on the model thread, while `getImage()` in the view is invoked on the EDT. – trashgod Oct 25 '13 at 15:05
  • Ok next() is invoked only on the model thread but the pixels it writes are concurrently read from another thread. What makes those writes visible? – maurizeio Oct 25 '13 at 18:18
  • `public synchronized BufferedImage getImage() {…}`? – trashgod Oct 25 '13 at 20:13
  • But that would only synchronize access to the reference field, not to the contents of the image... – maurizeio Oct 25 '13 at 21:33
  • 1
    As well as `Raster` updates that happen before the synchronization point. If this is not sufficient, consider this alternate [approach](http://stackoverflow.com/a/16880714/230513) that publishes a `Raster` from a `SwingWorker` in the form of a `TexturePaint`. – trashgod Oct 25 '13 at 22:16