几组线程同步代码测试
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(); }
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)); }
使用 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(); } }

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();//回到家了! } } }

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(); } } }
采用Barrier方式改写上面2的代码后发现,时间由原来的1.5秒变成42秒,Barrier的使用还是要慎重
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
2013-04-06 读写Ini文件