1

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

 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 行。既然这是一个本地引用,那么每个线程会保持不同的引用还是 synchornizedStoredProcedureCall 会覆盖对 thingOne 的引用,因为 doSomethingWith 即将使用它?

如果 thingOne 被声明为 final 或者我让它不可变怎么办?

4

6 回答 6

4

每个线程会维护不同的引用还是 synchornizedStoredProcedureCall 会覆盖对 thingOne 的引用,因为 doSomethingWith 即将使用它?

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

只要doSomethingWith(...)and调用是线程安全的并且doSomethingElseWith(...)使用thingOne参数和常量(等),保护应该没问题。synchornizedStoredProcedureCall()

正如@Marko 指出的那样,没有看到Thing类,我们不能保证它是线程安全的并且不存储内部状态。

于 2013-01-04T16:59:06.827 回答
2

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

于 2013-01-04T17:04:10.970 回答
0

无论如何,Thingone 都是线程安全的,因为它在堆栈上被声明为 threadlocal。如果 thingone 是一个没有在方法中声明的实例变量,你就会遇到问题;但事实并非如此 - 所以你没有。

于 2013-01-04T16:58:55.377 回答
0

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

于 2013-01-04T17:02:14.060 回答
0

你需要确保它thingOne没有被共享。即使它是从同步方法返回的,如果它是从返回的单例的成员synchornizedStoredProcedureCall,您的实现也不再是线程安全的。

于 2013-01-04T17:09:26.560 回答
0

每个线程将维护一个不同的引用。如果 someMethod 是静态的,情况也是如此。

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

于 2013-01-04T17:14:02.417 回答