【问题标题】:Class-level locking类级锁定
【发布时间】:2013-12-16 10:50:29
【问题描述】:

我有一个带有一些静态方法的类。这些静态方法使用相同的资源(数据列表)。我希望这个数据列表是线程安全的。由于同一类中的静态方法数量正在使用相同的数据列表。我不能简单地使用 lock/Monitor 在多线程环境中保护我的代码。如何确保只有一个线程正在执行我的类的任何方法,而其他线程应该等待该线程退出,无论他们想在我的类中运行相同的方法还是不同的方法。我怎样才能做到这一点? 这是一些需要澄清的代码。我的工作是写MyLibraryClass

class Program
{
    static void Main(string[] args)
    {
      
        var t1 =System.Threading.Tasks.Task.Factory.StartNew(MyLibraryClass.A);

        var t2 = System.Threading.Tasks.Task.Factory.StartNew(MyLibraryClass.B);

        t1.Wait();
        t2.Wait();
        Console.WriteLine("Completed. Press any key to continue");
        Console.ReadKey();
    }

}

class MyLibraryClass
{

    static List<int> items = new List<int>();
    static MyLibraryClass()
    {
        items.Add(5);
        items.Add(4);
    }
    public static void A()
    {
        foreach (var a in items)
        {
            Console.WriteLine(a);
            System.Threading.Thread.Sleep(300);
        }
    }

    public static void B()
    {
        System.Threading.Thread.Sleep(200);
        Console.WriteLine("Adding Number");
        items.Add(9);
    }
}

【问题讨论】:

  • How can I ensure that only one thread is executing any method of my class... - 不使用多线程
  • 在所有那些在所有情况下都适用于同一个private static readonly object _lock = new object();的方法中放置一个锁块......? :) 尽管对此类使用多线程毫无意义,因为您将强制顺序执行。
  • @DGibbs 先生的声明相当轻率。 OP 可能正在编写供其他工程师使用的代码。代码甚至可能是产品。如果并发会导致问题,它肯定会希望确保调用序列化。
  • @PatrykĆwiek 共享资源是唯一正在发生的事情是非常罕见的,所以它不是“毫无意义”
  • @MarcGravell 确实如此,但多线程环境中的静态、可变数据让我什至想都不敢想。

标签: c# .net multithreading


【解决方案1】:

我不能简单地使用锁/监视器来保护我在多线程环境中的代码。

是的,你可以。这正是你应该做的。

如何确保只有一个线程正在执行我的类的任何方法,而其他线程应该等待这个线程退出,无论他们想在我的类中运行相同的方法还是不同的方法。我怎样才能做到这一点?

通过使用lock/Monitor。或其他一些线程隐喻,例如线程安全集合,但lock 是最简单的。当您处理实际上是多个操作的原子单元时,线程安全的集合需要更多的思考(例如,如果缺少,则测试然后添加)。

另一个提示是:不要使用可变数据的静态列表:这很少是个好主意。

【讨论】:

  • 锁定/监控确保代码块一次由一个线程执行。但我的问题不是保护单个代码块。我有两个方法 A 和 B。如果线程 T1 想要执行方法 A 而线程 T2 想要执行方法 B,那么 T1 和 T2 不应该并行运行这些方法。只有 T1 运行完方法 A,T2 才能运行方法 B。
  • @ZafarYousafi 方法 A 和 B 应该在同一个成员上建立锁定。
  • @ZafarYousafi - 这不是一个合乎逻辑的要求。线程安全始终与保护数据(状态)有关,而与方法无关。
  • @ZafarYousafi 如果您无法控制访问共享状态的方法,那么您就是“SOL”,并且需要考虑某种从一开始就考虑线程安全的重构。您可能对线程安全集合有一些的运气,但这些并不是灵丹妙药(经典示例是“检查是否在列表中,然后添加”)。另一种选择是:停止使用可变共享状态。
  • @ZafarYousafi 再一次,没有任何改变;你有相同的选择: 1:在方法中使用lock,用于与状态对话的特定位 - 你说这不是一个选项; 2:在任何调用方法中使用lock,并接受整个方法将彼此同步,或 3:使用线程安全集合,但要理解任何基于集合的状态(而不是简单地添加等)本质上是错误的并且容易受到线程竞争的影响,或者 4:正确重构代码,使代码不会直接与共享状态对话
【解决方案2】:

您可以为 MyLibraryClass 使用 [同步] 属性。这将确保整个类是线程安全的。

【讨论】:

猜你喜欢
  • 2023-03-04
  • 2013-09-23
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多