c#两种同步结构

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

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

 

直接上代码,进行比较;

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication12
{
    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();
        }


    }

    //在来比较一些lock的方式呢;


    class Program
    {
        static object locker = new object();
        static void Test()
        {
            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);
            }

            //lock方式的比较 已确保原子性的操作;
            sw = Stopwatch.StartNew();
            for (Int32 i = 0; i < iterations; i++)
            {
                lock (locker) { x++; }  //这个在单线程的模式下 进行的比较
            }
            Console.WriteLine("Incrementing x in lock:{0:N0}", sw.ElapsedMilliseconds);
        }
        static void Main(string[] args)
        {

            Thread.Sleep(3000);
            Console.WriteLine("start...");
            Test();//结果表明基于内核模式的同步比基于用户模式的同步慢了数十倍

        }

    }
}

 

然后直接看结果;

 

 

 

 lock 在这里比较的意义不大;在这种情况下lock的效率可定是最高的。请记住是在这种情况下;

 

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

 

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

 

这个只是一个初步的了解,后面,会再花点时间来讨论和研究这个东东;

posted @ 2017-08-30 09:58  咕-咚  阅读(192)  评论(0编辑  收藏  举报