【问题标题】:Stateless Singletons and Concurrency无状态单例和并发
【发布时间】:2016-04-25 22:09:29
【问题描述】:

我有一个关于无状态单身人士的问题。我还有一个关于状态单例的问题。

无状态单例服务是帮助实现可扩展性的好方法。构建我维护的项目的程序员基本上说不会有并发问题,因为“它只是代码”(即 Singleton 类)。这意味着该类没有类级别的变量。这只是方法。

这就是我对 C# 的了解有点模糊的地方。是否存在两个用户通过单独的 Web 请求同时点击无状态单例的问题?他们能否同时采用相同的方法?这甚至可能吗?如果是这样,这是否意味着他们将在该方法中使用相同的局部变量?听起来很混乱,所以我假设它不可能发生。我假设方法调用永远不会被其他用户污染。

我问过很多同事这个问题,没有人知道答案。所以这是一个棘手的问题。

我关于单例的问题通常是 2 个或更多并发用户读取单例的公共属性是否有任何问题。我只对阅读感兴趣。如果属性不在锁定块内,是否有可能发生某种并发异常?或者并发、同时读取是否安全?我真的不想使用 lock 关键字,因为这是我不需要的性能损失。

谢谢

【问题讨论】:

  • 无状态有利于并发;除了创建全局变量之外,单例对任何事情都没有好处。谷歌从他们的代码库中删除了单例。你为什么坚持宣传它们?
  • 如果同时对同一个方法进行两次调用,每次调用都将拥有自己的堆栈和自己的一组局部变量。您只需要担心与共享变量的并发。
  • 你说“网络请求”,这是asp.net的东西吗? Lazy<> singleton 是线程安全的(我只是不明白你的问题的其余部分)。
  • @duffymo 我已经使用具有单例生命周期的服务一年了。它似乎运作良好,并且不难使用。您只需要记住在添加新方法时不要添加任何状态。我不认为它们在所有情况下都不好,而且随着流量的增加,它们肯定会最大限度地减少内存占用。
  • 如果您的服务是基于云的微服务,您可能会发现在重负载需要时需要多个实例。您的云可能会启动多个实例来处理紧急情况,然后在结束后让它们停止服务。那么“单例”是什么意思呢?关键是无国籍。抱歉,如果这是“幸存者”的一集,辛格尔顿将被选为 GoF 岛。还有一点:singleton or no 对性能没有意义。决定这一点的是实施和所做的工作。

标签: c# singleton singleton-methods


【解决方案1】:

单例是anti-pattern。无状态的单例更糟糕。如果某些东西不保持状态,甚至没有最微弱的理由让它成为单例。

无状态单例是一个纯粹的静态函数,来自喜欢添加模式而不考虑模式会实现什么的人。因为在这种情况下,他会注意到它一无所获。

如果您看到无状态单例,您可以安全地删除使其成为单例的所有代码。在类定义中添加static。完毕。比以前好多了。

我认为您对多线程(无论是否单例)感到非常困惑。我建议您阅读一本关于此的好书或教程,因为这里超出了简单答案的范围。如果您有共享资源(简单示例,非本地变量),那么您需要在多线程环境中特别小心。

如果您阅读的频率高于写作频率,使用ReaderWriterLock 而不是简单的lock 可能会有所帮助。见here

【讨论】:

  • 您已将合法的设计模式声明为反模式。无论情况或上下文如何,它都是反模式,没有例外。我很抱歉,但我不同意。必须小心单例。但我不认为它们是彻头彻尾的反模式。
  • 单例,即使是最好的,也是一种限制用户只有一个类实例的模式。我从来没有发现任何用途。如果我只想要一个,我将只实例化一个。如果我的程序只使用一个 int,我就不会创建 SingletonInt 类。限制一个没有状态的类的实例创建,因此没有理由实例化根本是这种模式被滥用的一个典型例子。这不是人们使用的模式,而是拥有他们需要的全局的借口。
  • 感谢您的意见。我确实重视我得到的回应。我可以看到单例服务的意义,最近有人告诉我 StackOverflow 本身使用单例服务(我需要验证它的来源)。你有一个实例,它只包含被调用的方法。无论有什么状态,它都是通过方法的参数传递的。将服务范围限定为请求(通过 IOC)并为其赋予状态绝对更容易。我认为整个想法是最小化内存占用并使用 1 个实例来实现。无论如何,它肯定不是全局变量
  • 我不是在谈论 IOC 的“单例”生命周期。没关系。这与具有单个实例的普通类没有什么不同。我说的是明确实现该模式。 是一种反模式。
  • 啊,好的。我应该澄清一下,我所指的单例是一个已由具有单例生命周期的 IOC 解决的对象。因此,不限于单个请求,它会一直存在,直到应用程序池回收或其他任何可能导致应用程序域关闭的情况。
猜你喜欢
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 2019-06-29
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多