加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

C#中的线程四(System.Threading.Thread)

发布时间:2021-05-21 05:21:50 所属栏目:大数据 来源: https://www.jb51.cc
导读:C#中的线程四(System.Threading.Thread) 1.最简单的多线程调用 ? ?System.Threading.Thread类构造方法接受一个ThreadStart委托,改委托不带参数,无返回值 1 public static void Start1() 2 { 3 Console.WriteLine( " this is main thread!:{0},{1} " ,Sys

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 }

?

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读