【问题标题】:best way to lock an object锁定对象的最佳方法
【发布时间】:2020-01-06 04:31:06
【问题描述】:

我正在用 C# 构建一个程序,其中有 2 个线程使用相同的对象。 第一个线程更新对象值,第二个线程将其打印到 GUI。

我正在寻找最correctclean的方式来实现线程之间的锁定机制。

我在我的程序(不是实际程序)中的实现示例:

namespace Test___Console
{
    public class Custom
    {
        public static object lockinObject = new object();
        public string name;
        public int value;
        public Custom(string name)
        {
            this.name = name;
        }
    }
    public class Program
    {
        public static object lockinObject = new object();
        static Thread firstThread;
        static Thread secondThread;
        static public Custom someData;
        static void Main(string[] args)
        {
            someData = new Custom("first");
            firstThread = new Thread(FirstThreadFunctions);
            secondThread = new Thread(SecondThreadFunctions);
            firstThread.Start();
            secondThread.Start();
            do
            {

        } while (true);
    }
    static void FirstThreadFunctions()
    {
        Random rnd = new Random();
        do
        {
            someData.value = rnd.Next();
            Thread.Sleep(1000);
        } while (true);
    }
    static void SecondThreadFunctions()
    {
        do
        {
            Console.WriteLine(someData.value.ToString());
            Thread.Sleep(1000);
        } while (true);
    }
}
}

我想到了 3 种方法来锁定 someData 对象

1.将带有锁定对象的get set添加到someData对象中。

2.将带有锁定对象的get设置添加到自定义类变量中。

3.用锁定语句封装所有使用相同数据对象的代码段(我最不喜欢的方法)。

我没有太多的编程经验,所以我问你处理这个问题的“正确”或“最干净”的方法是什么。

谢谢

【问题讨论】:

  • 你也可以锁定自己的班级var c = new Custom(); lock (c) {...}

标签: c# multithreading locking


【解决方案1】:

您希望尽可能地限制您的阻塞代码。以你的情况为例。

实际上,您要做的是锁定一个对象并防止它在写入时读取。阅读其他阅读器时无需锁定它。

ReaderWriterLockslim 回复。然后在你的Custom 类中

public class Custom
{
    private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();

    private int currvalue;
    public int value {
        get {
            cacheLock.EnterReadLock();
            var retValue = currvalue;
            cacheLock.ExitReadLock();
            return retValue;
        }
        set {
            cacheLock.EnterWriteLock();
            this.currvalue = value;
            cacheLock.ExitWriteLock();
        }
    } 
}

这样,您将并发性限制为仅需要线程安全的当前对象,锁被非常紧密地应用于数据,因此不会轻易引入死锁并且仅用于写入操作。

【讨论】:

  • 最好的方法是为每组相关变量设置一个锁。即如果 var1 和 var2 完全独立但需要处理,则为每个创建一个新锁。如果 var2 在写入时需要锁定 var 1,请为这些使用通用锁。这一切都取决于上下文。限制锁定区域是您的目标。
  • 对不起,我删除了评论(试图从我的智能手机发表评论,但我无法跳行)。问题是:如果我的自定义类有多个变量怎么办?谢谢您的回答。你的意思是我需要添加 cacheLock.EnterReadLock(); (以及其他相应的命令)在每个相关变量的每个 get 和 set 中。如果变量是独立的,我需要声明另一个 ReaderWriterLockSlim secondCacheLock 变量并使用 secondCacheLock .EnterReadLock(); (以及其他相应的命令)。我理解正确吗?
  • 是的!正是这样。我知道这有点开销,但它会节省你的时间。
  • 这个答案是错误的。如果线程在进入/退出之间被取消或崩溃,您应该始终使用try... finally 来释放锁或面临死锁的风险。该问题还要求最好的锁定。对于这种情况,最好的锁是使用 Interlocked 类,因为这是一个原始类型。
  • Charles,我最后添加了确实使用 try 的文档。这只是一个例子。 Interlocked 确实适用于原语,尽管操作只需要一个属性示例。
猜你喜欢
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2013-01-22
相关资源
最近更新 更多