【问题标题】:thread safe for instance fields实例字段的线程安全
【发布时间】:2016-07-21 08:03:02
【问题描述】:

在为线程安全项目编程时,如何确定哪个字段应该是线程安全的。例如,我们在多线程项目中有一个名为 TestThreadSafe 的项目。

public class TestThreadSafe  {
    public AtomicLong pCounter = new AtomicLong();
    public AtomicLong mCounter = new AtomicLong();
    protected final ConcurrentMap<K, V> Map = new ConcurrentHashMap<K, V>();
    private ScheduledExecutorService ses;
    private String dir;
}

这里,为什么不将 ses 和 dir 定义为 final 或 volatile 字段?

【问题讨论】:

  • 我们不知道这些字段的用途。如果它们未在多线程上下文中使用,则不需要 volatile。如果您不更改引用,则不需要 final
  • TestThreadSafe 用于多线程上下文

标签: java multithreading thread-safety


【解决方案1】:

重点说明:

  1. 如果你的变量没有被多个线程修改,不要使用任何东西
  2. 如果你的变量引用在创建后没有改变,使用final
  3. 如果你的变量被单线程修改,被其他线程访问,使用volatile
  4. 如果您的变量被多个线程修改和访问: 一个。如果您的操作是原子操作,请使用 AtomicXXX - 单步事务 湾。如果您有要保护的代码块,请使用 synchronizedLock API

您可以找到有关高级并发构造的更多详细信息here

相关的 SE 问题:

What is the difference between atomic / volatile / synchronized?

What is meant by "thread-safe" code?

【讨论】:

    【解决方案2】:

    将字段标记为final 总是好的(您不会失去任何性能,但可以获得编译时检查和线程相关的奖励 - 字段将始终具有给定值,而不是默认值)。

    至于volatile - 它使 CPU 优化(缓存)消失,因此使用此类字段会更慢。

    如果您在线程之间共享给定的字段值,则应使用volatile - 其中一个线程正在向其写入数据,而多个 (>= 1) 线程从中读取数据。

    【讨论】:

    • 对实例字段变量修饰符感到困惑,哪些字段应在实例字段变量之前声明为 final、volatile 或其他内容。如何确定,如何决定,有什么标准可以做到吗?
    • 没有标准,如果有java会为你做。你需要看代码端自己决定。我个人在各处添加 final 修饰符并在构造函数中初始化字段。
    猜你喜欢
    • 2020-01-15
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多