几组线程同步代码测试

Posted 遗忘海岸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了几组线程同步代码测试相关的知识,希望对你有一定的参考价值。

1.

    public class A
    {

        public void MA()
        {
            lock (typeof(A))
            {
                Thread.Sleep(5000);
                Console.WriteLine("MA:" +DateTime.Now);

            }
        }
        public   void MB()
        {
            Thread.Sleep(100);
            Console.WriteLine("MB:" + DateTime.Now);
        }
    }
}



        private void button4_Click(object sender, EventArgs e)
        {
            var a=new A();
            var t = new Thread(a.MA);
            t.Start();
            Thread.Sleep(100);
            var t2 = new Thread(a.MB);
            t2.Start();
        }
View Code

MB会正常输出,只有lock了同个对象的代码段会产生同步等待

2.

 private void button5_Click(object sender, EventArgs e)
        {
            

            SendCount = 0;
            var arr = RequestStr3.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            var bytes = new List<byte>();
            foreach (var item in arr)
            {
                bytes.Add(byte.Parse(item, NumberStyles.HexNumber));
            }
            var paket = nRadiusPaket.Parser(bytes.ToArray());

            

            
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int j = 0; j < 30; j++)
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        try
                        {
                            UdpClient udp = new UdpClient();
                            udp.Connect("192.168.9.5", 1812);
                            udp.Send(paket.Paket, paket.Length);

                            System.Net.IPEndPoint RemoteIpEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
                            var rec = udp.Receive(ref RemoteIpEndPoint);
                            var retPaket = nRadiusPaket.Parser(rec);
                            Interlocked.Increment(ref SendCount);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            continue;

                        }
            
                    }
                  
                   // Console.WriteLine("线程" + Thread.CurrentThread.ManagedThreadId + ",退出!");
                }, null);
            }
       
            long bTime = Environment.TickCount;
            while (SendCount < 3000 && (Environment.TickCount - bTime) < 10000)
            {
                Application.DoEvents();
            }
            sw.Stop();
            Console.WriteLine("SendCount:" + SendCount);
            Console.WriteLine("耗时:" + sw.ElapsedMilliseconds);
            //Console.WriteLine(Encoding.ASCII.GetString(rec));
            //Console.WriteLine("---------------------");
            //File.WriteAllText(@"C:\\rpak.txt", BitConverter.ToString(rec));

        }
View Code

使用 Interlocked.Increment(ref SendCount);进行同步

 

3.使用Barrier,(代码摘自:.NET 4.0面向对象编程漫谈)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace UseBarrier
{
    /// <summary>
    /// 线程参与者必须实现的接口
    /// </summary>
    public interface IParticipant
    {
        void Go();
    }
    
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace UseBarrier
{
    /// <summary>
    /// 张三
    /// </summary>
    public class ZhangSan:IParticipant
    {
        /// <summary>
        /// 用于生成随机暂停的时间
        /// </summary>
        private Random ran = new Random();

        public void Go()
        {

            Console.WriteLine("张三出门,挤公交车……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100,300));
            Console.WriteLine("张三下了公交车,到了地铁站,买票坐地铁……");
             //随机暂停1到3秒
            Thread.Sleep(ran.Next(100,300)); 
            Console.WriteLine("张三到了鸟巢大门……");
            Program.barrier.SignalAndWait();  //等待会合
            //开始参观
            Console.WriteLine("张三在参观……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300)); 
             Program.barrier.SignalAndWait(); //参观结束
             Console.WriteLine("张三离开了鸟巢,到了地铁站,买票坐地铁回家……");
             //随机暂停1到3秒
             Thread.Sleep(ran.Next(100, 300));
             Console.WriteLine("张三离开了地铁站,坐公交车回家……");
 //随机暂停1到3秒
             Thread.Sleep(ran.Next(100, 300));
              Console.WriteLine("张三回到家了!");
              Program.barrier.SignalAndWait();//回到家了!

        }
    }

    /// <summary>
    /// 李四
    /// </summary>
    public class LiSi : IParticipant
    {
        /// <summary>
        /// 用于生成随机暂停的时间
        /// </summary>
        private Random ran = new Random();

        public void Go()
        {

            Console.WriteLine("李四出门,到了地铁站,买票坐地铁……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300));
            Console.WriteLine("李四到了鸟巢大门……");
            Program.barrier.SignalAndWait();  //等待会合
            //开始参观
            Console.WriteLine("李四在参观……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300));
            Program.barrier.SignalAndWait(); //参观结束
            Console.WriteLine("李四离开了鸟巢,到了地铁站,买票坐地铁回家……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300));
            Console.WriteLine("李四回到家了!");
            Program.barrier.SignalAndWait();//回到家了!
        }
    }

    /// <summary>
    /// 王五
    /// </summary>
    public class WangWu : IParticipant
    {
        /// <summary>
        /// 用于生成随机暂停的时间
        /// </summary>
        private Random ran = new Random();

        public void Go()
        {
 
            Console.WriteLine("王五出门,步行去鸟巢……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300));
            Console.WriteLine("王五到了鸟巢大门……");
            Program.barrier.SignalAndWait();  //等待会合
            //开始参观
            Console.WriteLine("王五在参观……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300));
            Program.barrier.SignalAndWait(); //参观结束
            Console.WriteLine("王五离开了鸟巢,步行回家……");
            //随机暂停1到3秒
            Thread.Sleep(ran.Next(100, 300));
            Console.WriteLine("王五回到家了!");
            Program.barrier.SignalAndWait();//回到家了!
        }
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace UseBarrier
{
    class Program
    {
        public static Barrier barrier = null;
        static void Main(string[] args)
        {
          
            Action<Barrier> PhaseAction = delegate(Barrier barier)
            {

                switch (barrier.CurrentPhaseNumber)
                {
                    case 0:
                        Console.WriteLine("\\n===============================");
                        Console.WriteLine("\\n同步阶段一:张三、李四和王五都到达了鸟巢,开始参观……");

                        Console.WriteLine("\\n===============================");
                        break;
                    case 1:
                    
                        Console.WriteLine("\\n===============================");
                            Console.WriteLine("等待10秒!");
                        Thread.Sleep(10000);
                        Console.WriteLine("\\n同步阶段二:参观结束,张三、李四和王五开始回家……");

                        Console.WriteLine("\\n===============================");
                        break;
                    case 2:
                        Console.WriteLine("\\n===============================");
                        Console.WriteLine("\\n同步阶段三:所有人都回到了家,啊,多么快乐的一天!\\n");

                        Console.WriteLine("\\n===============================");
                        break;

                }

            };
            //有3个线程参与
            barrier = new Barrier(3, PhaseAction);

            //创建3个参与者对象
            List<IParticipant> Participants = new List<IParticipant>
            {
                new ZhangSan(),
                new LiSi(),
                new WangWu()
            };
            Console.WriteLine("敲任意键Barrier示例开始演示...");
            Console.ReadKey(true);
            Console.WriteLine("\\n===============================");

            //启动3个线程
            List<Thread> ths = new List<Thread>();
            foreach (IParticipant man in Participants)
            {
                Thread th = new Thread(man.Go);
                ths.Add(th);
                th.Start();
            }
            //等待所有线程运行结束
            foreach (Thread th in ths)
            {
                th.Join();
            }

            Console.WriteLine("敲任意键退出……");
            Console.ReadKey();

        }
    }
}
View Code

 

采用Barrier方式改写上面2的代码后发现,时间由原来的1.5秒变成42秒,Barrier的使用还是要慎重

以上是关于几组线程同步代码测试的主要内容,如果未能解决你的问题,请参考以下文章

线程同步-使用ReaderWriterLockSlim类

线程同步测试

起底多线程同步锁(iOS)

在单独的线程中同步运行异步代码

多线程编程

配置 kafka 同步刷盘