C#中的线程四(System.Threading.Thread)
C#中的线程四(System.Threading.Thread) 1.最简单的多线程调用? ?System.Threading.Thread类构造方法接受一个ThreadStart委托,改委托不带参数,无返回值 1 public static void Start1() 2 { 3 Console.WriteLine("this is main thread!:{0},{1}",System.Threading.Thread.CurrentThread.CurrentCulture,Thread.CurrentThread.Name); 4 System.Threading.ThreadStart start = Method1; 5 Thread thread = new Thread(start); 6 thread.IsBackground = true; 7 thread.Start(); 8 Console.WriteLine(main thread other thing...); 9 } 10 Method1() 11 12 Console.WriteLine(this is sub thread!:{0},1)">13 Thread.Sleep(TimeSpan.FromSeconds(3)); 14 Console.WriteLine(sub thread other thing...15 } 注意thread.IsBackground=true,利用Thread创建的线程默认是前台线程,即IsBackground=false,而线程池中的线程是后台线程。 ?前台线程和后台线程的区别在于:当主线程执行结束时,若任然有前台线程在执行,则应用程序的进程任然处于激活状态,直到前台线程执行完毕;而换成后台线程,当主线程结束时,后台线程也跟着结束了。 2.给线程传送数据 ?? 这是使用ParameterizedThreadStart 委托来代替ThreadStart委托,ParameterizedThreadStart 委托接受一个带object的参数,无返回值 Start2() { 3 Customer c = new Customer { ID = aaa",Name = name }; 4 Console.WriteLine( 5 ParameterizedThreadStart start = Method2; 6 Thread thread = thread.Start(c); 8 Console.WriteLine( } 10 void Method2(object o) { 12 Console.WriteLine(13 Console.WriteLine(o.ToString()); 14 Thread.Sleep(TimeSpan.FromSeconds(15 Console.WriteLine(16 } ? ? 由此实例可以看出,我们将一个Customer 实例传入了新线程中,新线程可以直接读取此参数的信息。 Start4() 3 Customer c = Customer(); 4 //调用同一个对象,从而实现资源共享 5 ThreadStart ts = c.Increase; 6 Thread[] tArray = new Thread[20]; 7 for (int i = 0; i < 20; i++) 8 { 9 tArray[i] = Thread(ts); tArray[i].Start(); } 12 { 14 tArray[i].Join(); 15 16 Console.WriteLine(c.Number.ToString()); 17 18 void Method3(19 20 Customer c = o as Customer; 21 若不上锁,所以每次结果都不同 22 应该重新建立一个object进行上锁,因为外边还有可能访问到c这个实例 23 lock (c) 24 25 int j = 0; j < 1000; j++26 { 27 c.Number++28 } 29 } 30 } ?Customer类的定义如下: class Customer { 3 int Number 4 5 get 6 set 8 string ID 10 11 12 13 14 Name 16 17 18 19 public Customer() 20 21 Number = 022 23 Increase() 25 object o = new (); 26 (o) 27 28 1000; i++ { 30 Number++31 } 32 } 33 34 } 3.竞态条件 ? ? 来看竞态条件的定义: 如果两个或多个线程访问相同的对象,或者访问不同步的共享状态,就会出现竞态条件。 ? ? 竞态条件也是多线程编程的常犯的错误,如果代码不够健壮,多线程编码会出现一些预想不到的结果,我们来根据一个实例来看: RaceCondition() 3 ThreadStart method = ChangeState; 4 这里放出20个线程 5 6 { 7 Thread t = Thread(method); 8 t.Name = i.ToString() + aa t.Start(); } 12 2.线程调用的方法,改变状态值 13 ChangeState() 15 int loop = 0; loop < 1000; loop++ { 17 int state = 518 if (state == { 20 此处第一个线程进入后没来得及++操作,第二个线程又进入,此时第一个线程做了++操作,第二个 21 线程继续++,state的值变成7 22 state++23 7 { 25 没有试验成功 26 Console.WriteLine(state={0},loop={1}27 Console.WriteLine(thread name:{0} } 29 Console.WriteLine(state.ToString()); 30 } 32 } ?最简单的解决竞态条件的办法就是使用上锁-lock,锁定共享的对象。用lock语句锁定在线程中共享的变量state,只有一个线程能在锁定块中处理共享的state对象。由于这个对象由所有的线程共享,因此如果一个线程锁定了state,另一个线程就必须等待该锁定的解除。 ChangeState2() 3 100; loop++ 5 6 7 { 9 { 11 state++12 { 14 15 Console.WriteLine(16 Console.WriteLine( } } 21 } ?4.死锁 ? ? ? 在死锁中,至少有两个线程被挂起,等待对方解除锁定。由于两个线程都在等待对方,就出现了死锁,线程将无限等待下去。? ?5.几种同步方法 ????? 上面介绍了两种线程数据共享的办法,一旦需要共享数据,就必须使用同步技术,确保一次只有一个线程访问和改变共享状态。上面介绍了使用lock的方法防止竞态条件的发生,但是如果用不好的话会产生死锁。那么下面再介绍几种针对不同情况使用的线程同步方法。 (1)SyncRoot模式 ?下面创建一个类的两个版本,一个同步版本,一个异步版本 GeneralDemo 3 virtual bool IsSynchronized 5 get { return false; } 7 static GeneralDemo Synchronized(GeneralDemo demo) 9 if (demo.IsSynchronized) { SyncDemo(demo); } 13 return demo; 15 DoThis() { } 17 DoThat() 19 } 同步版本 2 private SyncDemo : GeneralDemo 3 4 object syncRoot = private GeneralDemo demo; 7 8 State 10 state; } 11 set { state = value; } 13 SyncDemo(GeneralDemo demo) 15 this.demo =override 19 get 21 23 24 25 26 (syncRoot) demo.DoThis(); 31 33 34 35 36 37 } 需要注意的是在SyncDemo类中,只有方法是同步的,对于这个类的成员调用并没有同步,如果试图用SyncRoot模式锁定对属性的访问,对state的访问变成线程安全的,仍会出现竞态条件 ?即这样做是不可取的: 1 public int State 2 { 3 get { lock (syncRoot) { return state; } } 4 set { lock (syncRoot) { state = value; } } 5 }最好的办法是把lock添加到调用State的地方,当然锁定状态递增还有一种更快的方式 (2)Interlocked 2 3 4 5 return Interlocked.Increment(ref state); 6 } 7 } (3)Monitor类 if (Monitor.TryEnter(syncRoot,500)) try 7 acquired the lock synchroized region for syncRoot 10 finally Monitor.Exit(syncRoot); } else { 17 didn't get the lock,do something else 19 } ? (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |