当前位置:  开发笔记 > 编程语言 > 正文

字符串属性本身是线程安全的吗?

如何解决《字符串属性本身是线程安全的吗?》经验,为你挑选了2个好方法。

C#中的字符串是不可变的和线程安全的.但是当你有一个公共吸气剂属性时呢?像这样:

public String SampleProperty{
    get;
    private set;
}

如果我们有两个线程,第一个是调用'get'而第二个是在"相同"时调用'set',会发生什么?

恕我直言,该集必须锁定为线程安全,如下所示:

private string sampleField;
private object threadSafer = new object();

public String SampleProperty{
    get{ return this.sampleField; }
    private set{
        lock(threadSafer){
            sampleField = value;
        }
    }
 }

Jon Skeet.. 41

大多数答案都使用"原子"这个词,好像原子变化都是需要的.他们通常不是.

这已在评论中提及,但通常不在答案中 - 这是我提供此答案的唯一原因.(关于以较粗粒度锁定,允许附加等内容的观点也是完全有效的.)

通常,您希望读取线程查看变量/属性的最新值.原子性无法保证这一点.作为一个简单的例子,这是一个阻止线程的方法:

class BackgroundTaskDemo
{
    private bool stopping = false;

    static void Main()
    {
        BackgroundTaskDemo demo = new BackgroundTaskDemo();
        new Thread(demo.DoWork).Start();
        Thread.Sleep(5000);
        demo.stopping = true;
    }

    static void DoWork()
    {
         while (!stopping)
         {
               // Do something here
         }
    }
}

DoWork可能永远循环,尽管写入布尔变量是原子的 - 没有什么可以阻止JIT缓存stoppingin 的值DoWork.要解决此问题,您需要锁定,生成变量volatile或使用显式内存屏障.这也适用于字符串属性.



1> Jon Skeet..:

大多数答案都使用"原子"这个词,好像原子变化都是需要的.他们通常不是.

这已在评论中提及,但通常不在答案中 - 这是我提供此答案的唯一原因.(关于以较粗粒度锁定,允许附加等内容的观点也是完全有效的.)

通常,您希望读取线程查看变量/属性的最新值.原子性无法保证这一点.作为一个简单的例子,这是一个阻止线程的方法:

class BackgroundTaskDemo
{
    private bool stopping = false;

    static void Main()
    {
        BackgroundTaskDemo demo = new BackgroundTaskDemo();
        new Thread(demo.DoWork).Start();
        Thread.Sleep(5000);
        demo.stopping = true;
    }

    static void DoWork()
    {
         while (!stopping)
         {
               // Do something here
         }
    }
}

DoWork可能永远循环,尽管写入布尔变量是原子的 - 没有什么可以阻止JIT缓存stoppingin 的值DoWork.要解决此问题,您需要锁定,生成变量volatile或使用显式内存屏障.这也适用于字符串属性.



2> Marc Gravell..:

引用类型字段的get/set(ldfld/stfld)是(IIRC)保证是原子的,所以这里不应该有任何损坏的风险.因此,从这个角度来看它应该是线程安全的,但我个人将数据锁定在更高的级别 - 即

lock(someExternalLock) {
    record.Foo = "Bar";
}

或者可能:

lock(record.SyncLock) {
    record.Foo = "Bar";
}

这允许您对原子操作对同一对象进行多次读取/更新,以便其他线程无法获得无效的对象状态

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有