线程同步

我们在设计应用程序时应尽量避免使用线程同步,因为会产生一些问题:

  1.它的使用比较繁琐,因为我们要用额外的代码把线程同时访问的数据包围起来,并获取和释放一个线程同步锁,如果我们在一个代码块忘记获取锁,就有可能造成数据损坏。

  2.使用线程同步会影响性能,获取和释放一个锁肯定是需要时间的吧,因为我们在决定哪个线程先获取锁时候, CPU必须进行协调,进行这些额外的工作就会对性能造成影响

  3.因为线程同步一次只允许一个线程访问资源,这样就会阻塞线程,阻塞线程会造成更多的线程被创建,这样CPU就有可能要调度更多的线程,同样也对性能造成了影响

所以在实际的设计中还是要尽量避免使用线程同步,因此我们要避免使用一些共享数据,例如静态字段。

using System;
using System.Diagnostics;
using System.Threading;

namespace InterlockedSample
{
    // 比较使用锁和不使用锁锁消耗的时间
    // 通过时间来说明使用锁性能的影响
    class Program
    {
        static void Main(string[] args)
        {
            int x = 0;
            // 迭代次数为500万
            const int iterationNumber = 5000000; 
            // 不采用锁的情况
            // StartNew方法 对新的 Stopwatch 实例进行初始化,将运行时间属性设置为零,然后开始测量运行时间。
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < iterationNumber; i++)
            {
                x++;
            }

            Console.WriteLine("Use the all time is :{0} ms", sw.ElapsedMilliseconds);

            sw.Restart();
            // 使用锁的情况
            for (int i = 0; i < iterationNumber; i++)
            {
                Interlocked.Increment(ref x);
            }

            Console.WriteLine("Use the all time is :{0} ms", sw.ElapsedMilliseconds);
            Console.Read();
        }
    }
}
运行结果:

 


不加锁的情况,得不到预期的结果:

使用Monitor实现线程同步

using System;
using System.Threading;

namespace MonitorSample
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                Thread testthread = new Thread(Add);
                testthread.Start();
            }

            Console.Read();
        }

        // 共享资源
        public static int number = 1;

        public static void Add()
        {
            Thread.Sleep(1000);
            //获得排他锁
            Monitor.Enter(number);

            Console.WriteLine("the current value of number is:{0}", number++);

            // 释放指定对象上的排他锁。
            Monitor.Exit(number);
        }
    }
}

使用ReaderWriterLock实现线程同步
using System;
using System.Collections.Generic;
using System.Threading;

namespace ReaderWriterLockSample
{
    class Program
    {
        public static List<int> lists = new List<int>();

        // 创建一个对象
        public static ReaderWriterLock readerwritelock = new ReaderWriterLock();
        static void Main(string[] args)
        {
            //创建一个线程读取数据
            Thread t1 = new Thread(Write);
            t1.Start();
            // 创建10个线程读取数据
            for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(Read);
                t.Start();
            }

            Console.Read();
                
        }

        // 写入方法
        public static void Write()
        {
            // 获取写入锁,以10毫秒为超时。
            readerwritelock.AcquireWriterLock(10);
            Random ran = new Random();
            int count = ran.Next(1, 10);
            lists.Add(count);
            Console.WriteLine("Write the data is:" + count);
            // 释放写入锁
            readerwritelock.ReleaseWriterLock();
        }

        // 读取方法
        public static void Read()
        {
            // 获取读取锁
            readerwritelock.AcquireReaderLock(10);

            foreach (int li in lists)
            {
                // 输出读取的数据
                Console.WriteLine(li);
            }

            // 释放读取锁
            readerwritelock.ReleaseReaderLock();
        }
    }
}

 


posted on 2019-03-13 15:39  1老王  阅读(121)  评论(0编辑  收藏  举报