如果非同步静态方法不修改静态类变量,那么它们是否安全?

Sle*_*led 144 java concurrency static multithreading thread-safety

我在想,如果您有一个静态方法同步,但并没有修改任何静态变量是线程安全的?如果方法在其中创建局部变量怎么办?例如,以下代码是否是线程安全的?

public static String[] makeStringArray( String a, String b ){
    return new String[]{ a, b };
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我有两个线程连续和同时调用这个方法,一个与狗(说"大丹狗"和"公牛狗")和另一个与猫(说"波斯语"和"暹罗语")我会得到猫和狗在同一个数组?或者猫和狗不会同时在同一个方法的调用内?

Tom*_*icz 210

这种方法是100%线程安全的,即使它不是static.当您需要在线程之间共享数据时,会出现线程安全问题 - 您必须注意原子性,可见性等.

此方法仅对参数进行操作,这些参数驻留在堆栈上以及对堆上不可变对象的引用.堆栈本身就是线程的本地,因此不会发生数据共享.

不可变对象(String在本例中)也是线程安全的,因为一旦创建它们就无法更改,并且所有线程都看到相同的值.另一方面,如果该方法接受(可变),Date您可能会遇到问题.两个线程可以同时修改同一个对象实例,从而导致竞争条件和可见性问题.

  • 堆栈当然是当前线程的本地,但您可以在该堆栈上引用共享对象.这不是示例中的问题,因为字符串是不可变的,但是如果可以从多个线程访问此传递的对象,则修改传递的参数的方法可能会出现线程安全问题. (43认同)
  • 正确答案.方法级变量在每个线程执行堆栈中复制. (4认同)
  • "堆栈本身就是线程本地的,所以不会发生数据共享." 我觉得这是事实,但我找不到任何人真正这么说.谢谢! (2认同)
  • 正如@TomaszNurkiewicz 提到的,如果我们传递一个可变对象引用,我们可能会进入竞争条件。即使该方法不以任何方式更改对象,这是否也成立?我的意思是,由于对象是可变的,它仍然会被归类为竞争条件吗?如果我们将 final 关键字添加到参数中会怎样? (2认同)

Kon*_*rus 28

一个方法在改变某些共享状态时只能是线程不安全的.它是静态的还是无关紧要的.

  • @Konrad_Garus这里的问题是局部变量是否构成共享状态,或者静态方法的堆栈是按线程还是共享. (3认同)

Dan*_*iel 12

该功能完全是线程安全的.

如果你考虑一下......假设如果不同会发生什么.如果不同步,每个常用函数都会出现线程问题,因此JDK中的所有API函数都必须同步,因为它们可能被多个线程调用.由于应用程序大部分时间都在使用某些API,因此多线程应用程序实际上是不可能的.

考虑它太荒谬了,所以只为你自己:如果有明显的原因可能存在问题,方法就不是线程安全的.试着总是考虑一下如果我的函数中有多个线程会怎么样,如果你有一个步进调试器并且一个接一个地推进第一个...然后第二个线程...也许第二个线程......会有问题吗?如果你找到一个,它不是线程安全的.

请注意,大多数Java 1.5 Collection类都不是线程安全的,除了那些陈述的类,如ConcurrentHashMap.

如果您真的想深入了解这一点,请仔细查看volatile关键字及其所有副作用.看一下Semaphore()和Lock()类,以及他们在java.util.Concurrent中的朋友.阅读课程周围的所有API文档.值得学习和满足.

对不起这个过于精细的答案.

  • "如果你考虑一下......假设如果不同会发生什么.如果没有同步,每个常用函数都会有线程问题,所以JDK中的所有API函数都必须同步,因为它们可能被多个调用线程".好点子! (2认同)