所以我有一个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或者我将其设为不可变,该怎么办?
答案 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实例有一个指向同一个对象的非静态字段,或者如果它们确实以线程安全的方式处理它们。