最终字段的线程安全 [英] Thread safety of final field

查看:93
本文介绍了最终字段的线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个JavaBean User ,它是从另一个线程更新的,例如:

Let's say I have a JavaBean User that's updated from another thread like this:

public class A {

    private final User user;

    public A(User user) {
        this.user = user;
    }

    public void aMethod() {
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                ...a long running task..
                user.setSomething(something);
            }

        });
        t.start();
        t.join();
    }

    public void anotherMethod() {
        GUIHandler.showOnGuiSomehow(user);
    }
}

此代码线程安全吗?我的意思是,当创建A实例并称为A.aMethod的线程读取用户字段时,它是否看到用户处于全新状态?如何以适当的线程安全方式进行操作?

Is this code thread safe? I mean, when the thread that created A instance and called A.aMethod reads user fields, does it see user in the fresh state? How to do it in appropriate thread safe manner?

请注意,我无法修改用户类,也不知道它本身是否是线程安全的.

Note that I can't modify the user class and I don't know if it's thread safe itself.

推荐答案

此代码线程安全吗? ...它看到用户处于全新状态吗?

Is this code thread safe? ... does it see user in the fresh state?

并不是特别的-user在代码中是最终的,除了不能替换外,对线程安全几乎没有任何影响.

Not especially - the fact that user is final in your code makes almost no difference to thread safety other than the fact that it cannot be replaced.

应更改的位是setSomething设置的实例变量.它应该标记为volatile.

The bit that should change is the instance variable that is set by setSomething. It should be marked as volatile.

class User {
  // Marked `volatile` to ensure all writes are visible to other threads.
  volatile String something;

  public void setSomething(String something) {
    this.something = something;
  }

}

但是,如果(如您建议的那样)您没有访问User类的权限,则必须执行创建内存障碍的同步.以其最简单的形式,您可以使用synchronized访问权限来包围对user的访问.

If however (as you suggest) you do not have access to the User class, you must then perform a synchronization that creates a memory barrier. In its simplest form you could surround your access to the user with a synchronized access.

synchronized (user) {
  user.setSomething(something);
}


添加了:-事实证明(请参见此处),实际上可以这样做:


Added :- It turns out (see here) that this can actually be done like this:

volatile int barrier = 0;
...
user.setSomething(something);
// Forces **all** cached variable to be flushed.
barrier += 1;

这篇关于最终字段的线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆