因为最近开始学习使用WCF,而WCF的一大特点就是传输数据前,进行序列化。
于是会出现多个线程同时序列化一个对象,于是开始思考,序列化是线程安全的么。
去查看MSDN,被告知:
此类型的任何公共静态(Visual Basic 中的Shared)成员都是线程安全的,但不保证所有实例成员都是线程安全的。
http://msdn.microsoft.com/zh-cn/library/y50tb888(v=vs.100).aspx
假设对象是一个普通的类,我们开4个线程对其属性进行不断的设置,同时开设一个线程进行序列化。
Student s = new Student(); Task t = new Task(() => { for (int i = 0; i < 100; i++) { s.ads2 = string.Format("task1{0}", i); Thread.Sleep(100); } } ); Task t2 = new Task(() => { for (int i = 0; i < 100; i++) { s.ads3 = string.Format("task2{0}", i); Thread.Sleep(100); } }); Task t3 = new Task(() => { for (int i = 0; i < 100; i++) { s.Name = string.Format("task3name{0}", i); Thread.Sleep(100); } } ); Task t4 = new Task(() => { for (int i = 0; i < 100; i++) { s.Adtress = string.Format("task4{0}", i); Thread.Sleep(100); } }); Task t5 = new Task(() => { try { for (int i = 0; i < 100; i++) { using (FileStream filestream = new FileStream(@"D:\data\123.txt", FileMode.OpenOrCreate)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(filestream, s); } Thread.Sleep(100); Console.WriteLine("Serilize Success {0}", i); using (FileStream fs = new FileStream(@"D:\data\123.txt", FileMode.OpenOrCreate)) { BinaryFormatter b = new BinaryFormatter(); Student s1 = b.Deserialize(fs) as Student; Console.WriteLine(s1.ToString()); } } } catch (Exception ex) { Console.WriteLine("Erro{0}", ex); } }); Console.WriteLine("Start"); t.Start(); t2.Start(); t3.Start(); t4.Start(); t5.Start(); Console.ReadLine();
运行结果,没有异常,线程安全
实验2,如果对象是一个集合类呢?开启2个线程不断的进行add或者remove(因为我需要的场景只需要add,所以只进行add验证),同时再开启2个线程同时进行序列化
List<Student> ss = new List<Student>(); Task t1 = new Task(() => { for (int i = 0; i < 100; i++) { lock (ss) { ss.Add(new Student()); Thread.Sleep(100); } } }); Task t4 = new Task(() => { for (int i = 0; i < 100; i++) { lock (ss) { ss.Add(new Student()); Thread.Sleep(103); } } }); Task t2 = new Task(() => { for (int i = 0; i < 100; i++) { using (FileStream fs = new FileStream(@"D:\data\234.txt", FileMode.OpenOrCreate)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, ss); Console.WriteLine("Serilize1 ss count{0}", ss.Count); Console.WriteLine("Serilize1 Done"); Thread.Sleep(101); } } }); Task t3 = new Task(() => { for (int i = 0; i < 100; i++) { using (FileStream fs = new FileStream(@"D:\data\345.txt", FileMode.OpenOrCreate)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, ss); Console.WriteLine("Serilize2 ss count{0}", ss.Count); Console.WriteLine("Serilize2 Done"); Thread.Sleep(102); } } }); Console.WriteLine("Start"); t1.Start(); t2.Start(); t3.Start(); t4.Start(); Console.ReadLine();
运行结果是线程安全。
结论是在多线程场景下,多个线程对同一对象进行序列化时,即使同时对象本身属性在不断被修改,或者同时进行add操作或remove操作,也是线程安全的。