使用私有静态方法使单例线程安全?
我有一个类,我想通过创建它的静态实例来将其用作单例。当然我也希望它是线程安全的。
假设我没有共享任何私人数据。但如果我没有记错的话,仍然存在一个问题,即当调用静态对象实例的方法时,方法内的变量在线程之间共享,并且会产生不可预测的结果。
但是,当调用真正的静态方法时,会创建一个新的堆栈帧,因此无论如何它都是线程安全的(对其自身而言)。再说一次,如果我没记错的话。
这种单例模式是线程安全的吗?
class Singleton
{
public object SomeMethod(object arg) {
return Singleton.SomeMethodImpl(arg);
}
private static object SomeMethodImpl(object arg) {
// is in unique stack frame?
object Result;
...
return Result;
}
}
如果您想知道为什么我不首先创建一个静态类 - 我需要一个基于接口的单例,并且具有不同的实现,作为策略模式的一部分。这不适用于静态类。
I've got a class I want to use as a singleton by creating a static instance of it. Naturally I also want it to be thread safe.
Assume I am not sharing any private data. But if I am not mistaken, there still remains the problem that when calling a method of a static object instance, variables within methods are shared across threads, and would have unpredictable results.
However, when calling a real static method, a new stack frame is created, so it is thread safe (unto itself) anyway. Again, if I am not mistaken.
Would this pattern for a singleton be thread safe?
class Singleton
{
public object SomeMethod(object arg) {
return Singleton.SomeMethodImpl(arg);
}
private static object SomeMethodImpl(object arg) {
// is in unique stack frame?
object Result;
...
return Result;
}
}
In case you are wondering why I don't just create a static class in the first place - I need to have a singleton that is based on an interface, and has different implementations, as part of a strategy pattern. This doesn't work for static classes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
只要您的方法没有从实例方法或全局范围变量获取状态,您的方法就是可重入且线程安全的。它不一定必须是静态的。就像这样:
这是完全线程安全的,并且可以根据需要调用任意次数。即使在方法内部定义变量也可以,只要它们是在方法之间共享的实例变量即可。
方法如:
上面的方法也是可重入且线程安全的。
一旦开始添加变量,无论它们是静态的还是来自不同范围的实例,您就会开始遇到线程安全问题。
在上面的示例中,
IncrementCounter()
方法不是线程安全的。As long as your method isn't getting state from an instance method or global scope variable your method is reentrant and thread safe. It doesn't necessarily have to be static. So something like:
That's perfectly thread safe and can be called as much as you like. Even defining variables inside of the method is fine as long as they are instance variables that are shared between methods.
A method such as:
The method above is also reentrant and thread safe.
As soon as you start adding variables whether they are static or instance that come from a different scope you start having problems with thread safety.
In the above example the
IncrementCounter()
method is not thread safe.如果我明白你的意思,那么你是对的。
即使多个线程调用此方法,它们也会在堆上创建不同的新变量并将它们分配给不同堆栈上的 Result。
你面临的唯一危险是如果你有私人领域。
方法中的变量是临时的,仅对该方法调用可见。稍后或并发方法调用分别重新创建这些变量。
您唯一关心的是静态或实例字段。这些需要同步。
If I understand what you mean, then you're correct.
Even if multiple threads call this they will create different new variables on the heap and assign them to Result on different stacks.
The only danger you'd be in is if you had private fields.
Variables within a method are temporary and only visible to that method call. Later or concurrent method calls recreate those variables separately.
Your only concern is static or instance fields. Those would need to be synchronized.
由于您指定的原因,上面的代码是线程安全的。我看到的问题是你没有实现单例。
您主要担心的是线程安全吗?如果是这样,线程安全通常适用于线程之间共享的对象实例。这意味着只要您不跨线程共享普通对象或在类级别创建静态数据就应该没问题。
我添加了一个使用带有接口的单例的示例,无论有没有工厂。注意:我没有运行这段代码。
The code you have above is thread safe and for the reasons you've specified. The problem I see is you are not implementing a singleton.
Is your main worry about thread safety? If so, thread safety usually applies to object instance being share between threads. That means as long as you don't share a normal object across threads or create static data at the class level you should be ok.
I am adding an example of using singleton with interfaces, with and without a factory. Note: I didn't run this code.