Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Concurrent Exception

Hi I have a paint method that is drawing an image and I have another method that is constantly modifying the image to be drawn however I experience concurrency exceptions now and again. What is the most efficient way to resolve this please? I know I could use synchronized blocks on the buffered image but then it throws up warnings on synchronizing a none final variable.

private BufferedImage img;

public void modImage(BufferedImage image) { 
     img = image;
}

public void paintComponent(Graphics g) {
    if (img != null) {
        g.drawImage(img, 0, 0, this);
    }
}
like image 758
haz hazzz Avatar asked Apr 26 '26 13:04

haz hazzz


2 Answers

you could sync on instance,

private BufferedImage img;

public void modImage(BufferedImage image) { 
     synchronized(this){
         img = image;
     }
}

public void paintComponent(Graphics g) {
    synchronized(this){
    if (img != null) {
        g.drawImage(img, 0, 0, this);
       }
    }
}
like image 193
Low Flying Pelican Avatar answered Apr 28 '26 01:04

Low Flying Pelican


You have a race condition because the value of img can changed in another thread between the if conditional and the use of img in drawImage

if (img != null) {                     // <-- img can be non-null here
    g.drawImage(img, 0, 0, this);      // <-- img can now be null
}

You can assign img to a local variable, then use the local variable in-place of img in the above code. The local variable will remain constant even if img is changed to a different object in another thread

final BufferedImage localImg = img;      // <-- localImg won't change locally
if (localImg != null) {
    g.drawImage(localImg, 0, 0, this);
}

In addition to this, img should be declared as volatile so its value is not cached thread-locally; changes in one thread will be seen by others.

private volatile BufferedImage img;

Bear in mind that declaring a variable as volatile will cause synchronization to occur whenever that variable is accessed; so synchronization is still happening. However, synchronization occurs on the img reference itself, not the BufferedImage object to which it refers, so there are no issues here if img is null.

like image 30
pathfinderelite Avatar answered Apr 28 '26 03:04

pathfinderelite