为什么相同的字符串锁相同

时间:2019-03-15 11:42:15

标签: c#

我的应用程序出现了一些问题,我发现“锁定”导致了问题。我已将问题简化为更小的代码,可能会更小。但这会做到的。

 public partial class App
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            longProcessTimer = new System.Timers.Timer(3000);
            longProcessTimer.Elapsed += LongProcessElapsed;
            longProcessTimer.Start();
            SomeClass.Current.Start();
        }
        System.Timers.Timer longProcessTimer;
        static string LockingString = "TestString";
        private void LongProcessElapsed(object sender, EventArgs e)
        {
            Debug.WriteLine("Long Process Started");
            lock (LockingString)//this lock will block the sublock
            {
                longProcessTimer.Stop();

                Thread.Sleep(10000);//just for demo

                longProcessTimer.Start();
            }
            Debug.WriteLine("Long Process Ended");
        }
    }

    public class SomeClass
    {
        public static readonly SomeClass Current = new SomeClass();
        System.Timers.Timer SubTimer;
        Stopwatch stopWatch = new Stopwatch();

        protected string SubLockingString = "TestString";
        public SomeClass()
        {
            SubTimer = new System.Timers.Timer(500);
            SubTimer.Elapsed += SubTimerElapsed;
        }
        public void Start()
        {
            stopWatch.Start();
            SubTimer.Start();
        }
        private void SubTimerElapsed(object sender, EventArgs e)
        {
            SubTimer.Stop();
            stopWatch.Restart();
            lock (SubLockingString)
            {
                Debug.WriteLine("Inside sub lock, " + stopWatch.Elapsed);
            }
            SubTimer.Start();
        }
    }

现在,如果LockingString被锁定,它将也锁定SubL​​ockingString。但是,如果我更改任何字符串的值,锁将不会相互干扰。

我知道解决方案,但我很好奇为什么会发生?

2 个答案:

答案 0 :(得分:1)

您对String interning犯规。

当编译器看到两个具有相同值但在不同位置的字符串文字时,它将它们都转换为单个字符串对象。因此,您的LockingStringSubLockingString指向同一个对象-如果运行ReferenceEquals(LockingString, SubLockingString),您将返回true,这表明它们都是对相同基础字符串的引用

您应该只锁定专用的锁定对象。

写:

private [static] readonly object lockObject = new object();
private [static] readonly object subLockObject = new object();

相反。这样可以保证您有一个唯一的对象可以锁定。

答案 1 :(得分:1)

here所述,您应该避免使用String实例作为锁的参数。

这样做的原因是,运行时将对具有相同值的字符串使用相同的引用。这就是您的示例中发生的情况。