单例作用域类方法中的Java线程安全性

时间:2013-01-04 16:56:24

标签: java multithreading concurrency

所以我有一个Singleton类,其中包含一个由多个线程调用的非静态公共方法。在非静态方法中,我对由存储过程创建的对象进行本地引用,我推测这意味着“new”关键字在某处被调用。

 1 public void someMethod(SomeObjectParameter parameter) {
 2      
 3     Thing thingOne = synchornizedStoredProcedureCall(): 
 4     doSomethingWith(thingOne);
 5     doSomethingElseWith(thingOne);
 6
 7 }

目前,第3行到第5行位于同步代码块中,我希望将其简化为仅将存储过程调用作为同步。

所以......假设我们有两个线程,Thread1和Thread2。 Thread1即将执行第3行,而Thread2即将执行第4行。由于这是本地引用,每个线程是否会维护不同的引用,或者synornizedStoredProcedureCall会覆盖对thingOne的引用,因为doSomethingWith即将使用它?

如果将thingOne声明为final或者我将其设为不可变,该怎么办?

6 个答案:

答案 0 :(得分:4)

  每个线程都会维护一个不同的引用,或者synornizedStoredProcedureCall会覆盖对thingOne的引用,因为doSomethingWith即将使用它吗?

不同的线程有不同的堆栈。 thingOne存储在每个线程堆栈中,因此不能被其他线程覆盖。您还需要确保synchornizedStoredProcedureCall()每次都返回Thing的不同实例,而不是static或实例变量。两个线程都需要处理不同的Thing个实例。

只要doSomethingWith(...)doSomethingElseWith(...)调用是线程安全的,只能使用thingOne参数和常量(等),保护只需 {{ 1}}应该没事。

正如@Marko指出的那样,在没有看到synchornizedStoredProcedureCall()类的情况下,我们无法保证它是线程安全的而不是存储内部状态。

答案 1 :(得分:2)

答案取决于您未提供的大量细节。关于Thing类的许多细节都很重要:它可能有一些内部共享状态可能不是线程安全的(参见 Flyweight 设计模式)。这些事实必须记录在Javadoc类中;否则很难从源代码中找到它。

答案 2 :(得分:0)

无论如何,Thingone是线程安全的,因为它在堆栈上被声明为threadlocal。如果thingone是未在方法中声明的实例变量,则会出现问题;但它不是 - 所以你没有。

答案 3 :(得分:0)

你的thingOne是局部变量。它是线程安全的。每个线程都有自己的本地副本。

答案 4 :(得分:0)

您需要确保不共享thingOne。即使它是从synchronized方法返回的,如果它是从synchornizedStoredProcedureCall返回的单例的成员,则您的实现不再是线程安全的。

答案 5 :(得分:0)

每个线程都会保持不同的引用。如果someMethod是静态的,那就是这种情况。

您仍然必须确保Thing实例是线程安全的themslef。例如。 Thing类没有静态字段,也没有两个Thing实例有一个指向同一个对象的非静态字段,或者如果它们确实以线程安全的方式处理它们。