C#学习笔记 线程同步

多个线程同时操作一个数据的话,可能会发生数据的错误。这个时候就需要进行线程同步了。线程同步可以使用多种方法来进行。下面来逐一说明。本文参考了《CLR via C#》中关于线程同步的很多内容。

用户模式同步

易变构造

当对32位及32位以下变量的读写时,CLR保证读写操作是原子性的。也就是说bool、char、int等类型的变量可以一次性读取或者写入。但是对于long、ulong这些64位数据类型来说,就有可能不是原子操作。此外,由于编译器优化的存在,这些语句执行的顺序可能和编写代码时的顺序不同。这样的话,在多线程的环境下就有可能会出现同步问题。鉴于此,FCL提供了Volatile类,用来控制变量的读写和编译器的优化,这样的访问称为易变访问。

Volatile是一个静态类,包含了对于各种基元数据类型已经泛型类型的Write和Read方法。使用这些方法,可以做到:

  • 禁止编译器进行任何优化,对变量进行原子操作,只有在调用读写方法的时候才将值读取或写入。
  • 插入内存屏障,按照编码顺序,Write方法之前的存取操作必须在调用Write方法之前完成,Read方法之后的存取操作必须在调用Read方法之后完成。

这里有一个例子,在使用发布模式运行(非调试)程序的时候,代码行为会发生变化,导致死循环。原因如下:编译器发现在Work方法中,continue的值并没有发生改变,所以会将代码优化为在while循环之前求值,然后每次循环直接使用这个值。所以,优化后的代码while循环会直接变成死循环。从而导致程序出现问题。这也告诫我们:在多线程的环境下,对于程序应该引起足够的重视,有可能出现一些正式发布时才会出现的问题。

//当启用发布模式时,该类的行为会发生变化
//由于优化导致程序进入死循环
static class ProblemA
{
    //添加volatile关键字即可保证正确
    static bool continued = true;
    public static void ShowProblem()
    {
        Console.WriteLine("运行3秒之后停止工作:");
        Thread t = new Thread(Work);
        t.Start();
        Thread.Sleep(3000);
        continued = false;
        Console.WriteLine("等待工作结束...");
        t.Join();
        Console.WriteLine("--------------------------------");
    }
    private static void Work(object state)
    {
        int n = 0;
        //优化会导致这里变为死循环 
        while (continued)
        {
            n++;
        }
        Console.WriteLine("循环结束时n的值是" + n);
    }
}

C#同时还提供了volatile关键字,标记为volatile的变量,对其的所有操作都是易变操作。但是由于只有少数情况下才需要进行易变读写,直接标记volatile关键字会影响性能。所以还是推荐使用Volatile静态类,只有在需要的时候才进行易变操作。

互锁构造

Volatile类只有Write和Read两个方法。而Interlocked类增加了更多的方法,并且所有方法都是原子操作并提供内存屏障。

下面的例子说明了Interlocked类的主要方法。Interlocked类在多线程环境下十分有用。注意Exchange和CompareExchange方法返回的都是交换之前的值。

public static void InterlockTest()
{
    int i = 5;
    Console.WriteLine("演示Interlocked的方法:");
    Console.WriteLine("增加一个值:");
    Console.WriteLine("增加之后的值:" + Interlocked.Increment(ref i));
    Console.WriteLine("减少一个值:");
    Console.WriteLine("减少之后的值:" + Interlocked.Decrement(ref i));
    Console.WriteLine("用一个值交换:");
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值