【问题标题】:Why static class and singleton pattern class are not thread safe?为什么静态类和单例模式类不是线程安全的?
【发布时间】:2013-02-18 12:37:23
【问题描述】:

是的,目前我正在学习 C# 语言规范和可能的可破译教程。我阅读了多个关于线程安全单例类的问题和答案/文章。

以下是我已经浏览过的帖子:

我读的越多,我就越沉迷于信息。有人可以指导我更好地了解

1) 为什么开发人员关心线程安全?

2) 如何确定静态类/单例类不是线程安全的? (试用示例代码/示例教程会很棒,因为我喜欢正确学习这些基础知识)

【问题讨论】:

  • 这是一个安全或不安全的实现——不是“一般的单例”。
  • "why do developers care about thread-safety?" - 因为他们喜欢他们的代码,就像他们喜欢 thAsynchronous.eir 妙语一样。
  • @David 这是我见过的最好的解释。永远。
  • @David thAsynchronous.eir punchlines 这有点超出我的想象。你的意思是异步的吗?我只想知道线程环境中静态类带来的风险的正确图景。一个例子将不胜感激。

标签: c# static thread-safety singleton


【解决方案1】:

单例模式有多种版本,有些是线程安全的,有些不是:

您可以阅读 Jon Skeet 关于这些模式的文章。

http://csharpindepth.com/articles/general/singleton.aspx

线程安全对于确保您使用正确的值非常重要。

在以下示例中,两个线程调用一个方法,该方法意味着将值 x 设置为 25,如果它是 5,则将它乘以 5。

现在可以出现这样一种情况,主线程在x为5的时候进入if块,开始执行doSomething方法,然后是SecondThread,在x还是5的时候进入if循环,然后主线程A将x修改为25,然后SecondThread会修改为125。

所以这里我们需要某种同步,这样不超过一个线程可以同时修改 x。

private int x = 5;

        private void dosomething()
        {
        }
        private void multXby5if5() // Should make x =25, by multiplying 5  if it was 5, finally x should be 25
        {

            if (x == 5) // State A: SecondThread reaches here while x is still 5
            {
                dosomething(); //State A : Main thread reaches here

                x = x*5; // State B: Then Main Thread comes and makes x =25, then later SecondThread will come make x*5=25*5=125,

            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread tr = new Thread(multXby5if5);
            tr.Name = "SecondThread";
            multXby5if5();
            tr.Start();
        }

这不是最好的例子,但我希望它会对你有所帮助。

【讨论】:

  • 文章+1。我的问题是更好地了解线程环境中这些类中实际发生的情况。尽管您的最后一句话仍然是我正在寻找的答案。你能提供我证明nooby的示例文章吗? :)
  • 谢谢。我也在尝试各种文章和你的教程。请允许我有时间回来。
【解决方案2】:

为什么静态类和单例模式类不是线程安全的?

谁说所有单例模式类都不是线程安全的?使类线程安全

的许多方法

请看这里:http://csharpindepth.com/Articles/General/Singleton.aspx

【讨论】:

    【解决方案3】:
    1. 当您想提高性能时,您会遇到必须使用线程的情况,因此在使您的应用程序线程安全时,您可以避免一些竞争情况。

    2. 静态类和单例类将共享应用程序整个实例的值。当您从多个线程访问该对象时,您可以重用或覆盖也被另一个对象使用的变量。这将导致一些非常奇怪的输出,有时很难找到发生了什么,因为在测试用例中模拟它并不容易。您可以在您的方法中实现lock 以在这些类中引入线程安全

    【讨论】:

    • 拥有静态/单例类(具有非实例化方法)以确保可重用组件行为安全/封装的重点不是吗?例如在线程环境中,多个组件可以在一个静态类/接口中实现静态方法。像 100 个用户不断登录到数据库系统/ATM 系统。那怎么可能不是线程安全的? :) 你能再澄清一点吗?
    • 这就是死用。我想解释的是,静态类和单例类包含的值是为整个应用程序共享的。因此,每当您将值存储在静态或单例中时,您都需要确保您希望该变量适用于整个应用程序。
    • 如果你将 2 个方法添加到一个单例类中,他首先设置一个变量,然后在第二个中使用第一个变量执行一些功能。你可能会遇到这样的情况,变量由线程A设置,然后由线程B设置,该方法对线程A执行,然后对B执行。对于线程A的方法将产生无效结果
    • 但是如果我从静态(接口)的角度来看,那么它不知道组件(对象)正在使用什么数据,因为它没有实现。每个类对象都在各自的类中单独实现静态方法。也许你的说法更适合单例类。但不适用于静态类。我在正确的轨道上吗? :)
    • 静态类与接口非常不同。接口没有实现。但是静态类可以。您可以在静态类上遇到与单例相同的问题。你的变量将是私有静态
    【解决方案4】:

    一般来说,单例模式不是线程安全的,因为每次线程请求实例时,容器都会移交同一个实例。这可能导致多个线程具有相同的实例。

    但是有一些方法可以让你的单例线程安全。

    【讨论】:

    • 我假设你的意思是没有任何状态(只有方法)的单例类是线程安全的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2015-03-24
    • 1970-01-01
    • 2014-09-20
    • 2015-07-24
    相关资源
    最近更新 更多