浅谈.NET下的多线程和并行计算(十三)CLR via C#第三版阅读笔记(2)

简介: 线程同步的问题 1) 我们必须找到代码中所有可能被多个线程同时访问的资源,然后使用线程同步来保护资源,并且我们没有办法来验证是不是正确进行了线程同步,包括是否有遗漏和是否对不需要同步的资源进行同步。 2) 线程同步是有损性能的,如果某个操作大量执行,并且这个操作原先的执行时间非常短,那么如果我们对这段操作前后进行锁的申请和释放的话性能可能下降一个数量级。

线程同步的问题

1) 我们必须找到代码中所有可能被多个线程同时访问的资源,然后使用线程同步来保护资源,并且我们没有办法来验证是不是正确进行了线程同步,包括是否有遗漏和是否对不需要同步的资源进行同步。

2) 线程同步是有损性能的,如果某个操作大量执行,并且这个操作原先的执行时间非常短,那么如果我们对这段操作前后进行锁的申请和释放的话性能可能下降一个数量级。

3) 线程同步可能导致更频繁的线程创建和上下文的切换。

当然,只有在下面的情况下才需要线程同步,换句话说我们尽量不要使用下面的方案来导致线程同步:

1) 只有写操作, 如果只是访问只读对象,即使多个线程同时访问也不会改变资源,因此不需要同步,当然如果有写操作的话,即使是读操作也要考虑是不是需要同步。

2) 引用类型或者是可变的类型,如果访问的都是值类型(这里不说比如寄存器缓存的特殊情况)或者说类型是不可变的(比如string),那么我们对类型的获取和改写都是基于新的类型而不是多个线程的共享资源,因此不需要同步。

3) static静态资源,这也就是资源访问域的问题,如果这个资源并不会被多个线程访问到,也就是这个资源属于每个线程本身的,那么当然不需要同步。

最后,微软确保FCL所有静态方法线程安全,但由于性能问题FCL不保证所有实例方法线程安全,我们需要自己实现线程同步。对于我们自己的类库最好也遵从这个标准。

 

两种同步结构

1) 用户模式,硬件提供支持,速度非常快,但是在block的时候消耗CPU资源,在未争用的时候不损失性能

2) 内核模式,操作系统提供支持,速度比较慢,但是很灵活(比如可以设定超时时间,可以等待一组同步结构都可用的时候继续)并且和用户模式想法的是在block的时候可以不消耗CPU

作者进行了一个性能测试:

class Program
{
    static void Main(string[] args)
    {
        Int32 x = 0;
        const Int32 iterations = 5000000;
        Stopwatch sw = Stopwatch.StartNew();

        SimpleSpinLock ssl = new SimpleSpinLock();
        for (Int32 i = 0; i < iterations; i++)
        {
            ssl.Enter(); x++; ssl.Leave();
        }
        Console.WriteLine("Incrementing x in SimpleSpinLock: {0:N0}", sw.ElapsedMilliseconds);
        using (SimpleWaitLock swl = new SimpleWaitLock())
        {
            sw = Stopwatch.StartNew();
            for (Int32 i = 0; i < iterations; i++)
            {
                swl.Enter(); x++; swl.Leave();
            }
            Console.WriteLine("Incrementing x in SimpleWaitLock: {0:N0}", sw.ElapsedMilliseconds);
        }
    }
}

struct SimpleSpinLock
{
    private Int32 m_ResourceInUse;
    public void Enter()
    {
        while (Interlocked.Exchange(ref m_ResourceInUse, 1) != 0)
        {
        }
    }
    public void Leave()
    {
        Thread.VolatileWrite(ref m_ResourceInUse, 0);
    }
}

class SimpleWaitLock : IDisposable
{
    private AutoResetEvent m_ResourceFree = new AutoResetEvent(true);
    public void Enter()
    {
        m_ResourceFree.WaitOne();
    }
    public void Leave()
    {
        m_ResourceFree.Set();
    }
    public void Dispose() 
    {
        m_ResourceFree.Close();
    }
}

结果表明基于内核模式的同步比基于用户模式的同步慢了数十倍:

image

有关内核模式的各种结构我们在之前的文章中介绍了很多,在这里再补充一下两种用户模式的同步结构:

1) Volatile

两个作用一是防止编译器JIT甚至CPU对代码和指令等进行优化(比如跳过判断,调整代码次序),二是防止多核CPU分别在自己的寄存器中缓存了值导致的不一致性,让值始终从内存中读取。

2) Interlocked

Interlocked.Exchange和Interlocked.CompareExchange分别用于确保赋值操作和比较赋值操作的原子性,值得一提的是,Interlocked.Exchange并没有提供bool重载,我们可以使用int的0和1替代。还有,Interlocked.Read只提供了long重载,那是因为读一个long值的任何操作在32位操作系统上不是原子行为,而在64位操作系统上long的读操作是原子的。

作者: lovecindywang
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
1月前
|
并行计算 安全 Java
C# .NET面试系列四:多线程
<h2>多线程 #### 1. 根据线程安全的相关知识,分析以下代码,当调用 test 方法时 i > 10 时是否会引起死锁? 并简要说明理由。 ```c# public void test(int i) { lock(this) { if (i > 10) { i--; test(i); } } } ``` 在给定的代码中,不会发生死锁。死锁通常是由于两个或多个线程互相等待对方释放锁而无法继续执行的情况。在这个代码中,只有一个线程持有锁,且没有其他线程参与,因此不
105 3
|
3月前
|
C# Python
C# 笔记1 - 操作目录
C# 笔记1 - 操作目录
29 0
|
3月前
|
C# Python
C# 笔记3 - 重载一系列像python那样的print()方法
C# 笔记3 - 重载一系列像python那样的print()方法
29 1
|
3月前
|
存储 C# C++
C# 笔记2 - 数组、集合与与文本文件处理
C# 笔记2 - 数组、集合与与文本文件处理
46 0
|
10月前
|
存储 网络协议 Java
C# 快速入门笔记
C# 快速入门笔记
C# 快速入门笔记
|
C# 开发工具
C#滑动拼图验证码实现笔记
C# 是一个现代的、通用的、面向对象的编程语言,它是由微软(Microsoft)开发的,由 Ecma 和 ISO 核准认可的。突发奇想,动手开发一个C#滑动拼图验证码,下面是我开发过程的记录。
C#滑动拼图验证码实现笔记
|
SQL 开发框架 算法
【读书笔记】《Effective C#》50条建议笔记整理
对《Effective C#:改善C#代码的50个有效方法》一书整理的读书笔记。
28075 5
【读书笔记】《Effective C#》50条建议笔记整理
|
数据采集 Java C++
【.NET 6】多线程的几种打开方式和代码演示
多线程无处不在,平常的开发过程中,应该算是最常用的基础技术之一了。以下通过Thread、ThreadPool、再到Task、Parallel、线程锁、线程取消等方面,一步步进行演示多线程的一些基础操作。欢迎大家围观。如果大佬们有其他关于多线程的拓展,也欢迎在评论区进行留言,大佬们的知识互助,是.net生态发展的重要一环,欢迎大佬们进行留言,帮助更多的人。
196 0
【.NET 6】多线程的几种打开方式和代码演示
|
机器学习/深度学习 算法 计算机视觉
EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)(下)
说明 动机 贡献 方法 发现 EagleEye剪枝算法 实验 实验1- 相关性的定量分析 实验2-基于自适应BN的评估方法的通用性 实验3-从修剪候选中选择最佳修剪策略的计算成本 实验4-Effectiveness of our proposed method 总结与讨论
119 0
EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)(下)
|
机器学习/深度学习 算法 计算机视觉
EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)(上)
说明 动机 贡献 方法 发现 EagleEye剪枝算法 实验 实验1- 相关性的定量分析 实验2-基于自适应BN的评估方法的通用性 实验3-从修剪候选中选择最佳修剪策略的计算成本 实验4-Effectiveness of our proposed method 总结与讨论
141 0
EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)(上)