gpt4 book ai didi

java - 如何知道 Java SE 类或方法是否线程安全?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:17:32 25 4
gpt4 key购买 nike

例如:

static private DateFormat df = new SimpleDateFormat();
public static void format(final Date date) {
for (int i = 0; i < 10; i++)
new Thread(new Runnable() {
public void run() {
System.out.println(df.format(date));
}
});
}

DateFormat 类被记录为不是一个同步类,但是如果我们只使用格式化方法,它不能改变整个类的状态吗?

假设它被声明为私有(private),如何确定代码是线程安全的?

修复此代码的最佳方法是什么?:

  1. 为每个线程使用不同的实例。

  2. 使用同步块(synchronized block)。

最佳答案

  • 对于标准的 Java SE 类,了解该类是否线程安全的最佳方法是仔细阅读其文档。始终阅读类文档和方法文档。如果说它不是同步的或不是线程安全的,那么您就知道它不是线程安全的。
  • 因此,DateFormat不是线程安全的。文档具体说:

    Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

  • 声明一个字段private 不会使您的实现线程安全。 private 只是表示外部类看不到该字段。让我们看看您的方法:

     for (int i=0;i<10;i++) 
    new Thread(new Runnable(){
    public void run(){
    System.out.println(df.format(date));
    }
    });

    您创建的Runnable 对象是匿名类。匿名类是内部类,它们可以访问周围类的私有(private)字段。如果不是这样,您的程序将无法编译 - 他们无法访问 df 字段。

    但他们可以。所以实际上您有 10 个线程都在访问您的一个 DateFormat 对象,由 df 引用。因为我们已经知道 DateFormat 不是线程安全的,所以您的程序不是线程安全的。

  • 此外,如果两个外部线程引用了您的对象(我的意思是其中包含 df 的对象。您没有给出类声明,所以我不知道它的名字是什么是)。他们引用了您类(class)的同一个实例。如果它们同时调用 format,它们都将使用相同的私有(private) df 运行 DateFormat.format。因此,这不会是线程安全的。
  • 要实现线程安全,您需要在对象上进行同步或使用某种其他类型的锁(一个锁用于所有可能访问它的线程),这正是文档中所说的。
  • 另一种方法是拥有一个完全本地的对象,它只对一个线程可见。不是字段 - 局部变量,它可以访问 DateFormat 的唯一创建实例(因此每次调用该方法时都会有一个新副本)。不过要小心匿名类!在您的示例中,即使 dfformat 方法的本地字段,它仍然不是线程安全的,因为您的所有线程都将访问同一个副本。

关于java - 如何知道 Java SE 类或方法是否线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32023377/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com