首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java并发异常

Java并发异常
EN

Stack Overflow用户
提问于 2015-04-30 07:52:25
回答 3查看 128关注 0票数 3

您好,我有一个正在绘制图像的paint方法,还有一个不断修改要绘制的图像的方法,但是我经常遇到并发异常。请问解决这个问题最有效的方法是什么?我知道我可以在缓冲的映像上使用同步块,但是它会在同步none final变量时抛出警告。

代码语言:javascript
复制
private BufferedImage img;

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

public void paintComponent(Graphics g) {
    if (img != null) {
        g.drawImage(img, 0, 0, this);
    }
}
EN

回答 3

Stack Overflow用户

发布于 2015-04-30 08:23:08

您有一个争用条件,因为在if条件和在drawImage中使用img之间,img的值可以在另一个线程中更改

代码语言:javascript
复制
if (img != null) {                     // <-- img can be non-null here
    g.drawImage(img, 0, 0, this);      // <-- img can now be null
}

您可以将img赋给一个局部变量,然后在上面的代码中使用局部变量来代替img。即使将img更改为另一个线程中的其他对象,局部变量也将保持不变

代码语言:javascript
复制
final BufferedImage localImg = img;      // <-- localImg won't change locally
if (localImg != null) {
    g.drawImage(localImg, 0, 0, this);
}

除此之外,应该将img声明为volatile,这样它的值就不会被线程本地缓存;一个线程中的更改将被其他线程看到。

代码语言:javascript
复制
private volatile BufferedImage img;

请记住,将变量声明为volatile将导致无论何时访问该变量都会发生同步;因此同步仍然会发生。但是,同步发生在img引用本身,而不是它所引用的BufferedImage对象上,因此如果imgnull,则不会有任何问题。

票数 1
EN

Stack Overflow用户

发布于 2015-04-30 08:39:33

你可以在实例上同步,

代码语言:javascript
复制
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);
       }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2015-04-30 09:17:51

这存在一个线程安全问题,因为在运行paintComponent方法时可以更改BufferedImage的内容。仅在ui类中使用同步和易失性并不能解决这个问题。

如果要添加同步,则需要确保对映像的任何修改也是同步的。这需要在涉及的每个类之间共享的某个对象上进行同步。

通过确保每次都将img设置为BufferedImage的副本或不同的实例,可以避免某些同步。不过,它应该仍然是易失性的,如果你想安全地将img设置回null,请检查探路者精英的答案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29956641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档