manbetx官方网站

C#多线程和线程池[转]C#多线程和线程池[转]

九月 30th, 2018  |  买球网站manbetx

1、概念

1、概念

  1.0 线程的以及经过的涉及和优缺点**

  1.0 线程的同进程的关联及优缺点**

  windows系统是一个差不多线程的操作系统。一个先后至少发生一个进程,一个进程至少发生一个线程。进程是线程的器皿,一个C#客户端程序开始于一个独的线程,CLR(公共语言运行库)为该过程创造了一个线程,该线程称为主线程。例如当我们创建一个C#控制台程序,程序的输入是Main()函数,Main()函数是始于为一个主线程的。它的效力主要
是发生新的线程和实行顺序。C#凡平等家支持多线程的编程语言,通过Thread类创建子线程,引入using
System.Threading命名空间。 

  windows系统是一个大多线程的操作系统。一个顺序至少有一个进程,一个经过至少发生一个线程。进程是线程的容器,一个C#客户端程序开始吃一个独门的线程,CLR(公共语言运行库)为该过程创造了一个线程,该线程称为主线程。例如当我们创建一个C#控制台程序,程序的入口是Main()函数,Main()函数是开始为一个主线程的。它的成效主要
是发出新的线程和履行顺序。C#凡相同家支持多线程的编程语言,通过Thread类创建子线程,引入using
System.Threading命名空间。 

基本上线程的长处 

差不多线程的长处 

1
2
1、 多线程可以提高CPU的利用率,因为当一个线程处于等待状态的时候,CPU会去执行另外的线程
2、 提高了CPU的利用率,就可以直接提高程序的整体执行速度
1
2
1、 多线程可以提高CPU的利用率,因为当一个线程处于等待状态的时候,CPU会去执行另外的线程
2、 提高了CPU的利用率,就可以直接提高程序的整体执行速度

大多线程的短:

多线程的瑕疵:

 

 

1
2
3
1、线程开的越多,内存占用越大
2、协调和管理代码的难度加大,需要CPU时间跟踪线程
3、线程之间对资源的共享可能会产生可不遇知的问题
1
2
3
1、线程开的越多,内存占用越大
2、协调和管理代码的难度加大,需要CPU时间跟踪线程
3、线程之间对资源的共享可能会产生可不遇知的问题

 

 

     1.1 前台线程和后台线程

     1.1 前台线程和后台线程

   
 
C#备受的线程分为前台线程和后台线程,线程创建时未做设置默认是前台线程。即线程属性IsBackground=false。

   
 
C#未遭的线程分为前台线程和后台线程,线程创建时未举行设置默认是前台线程。即线程属性IsBackground=false。

Thread.IsBackground = false;//false:设置为前台线程,系统默认为前台线程。
Thread.IsBackground = false;//false:设置为前台线程,系统默认为前台线程。

 区别与怎样行使:

 区别与哪以:

    这两边的区分就是是:应用程序必须运行了所有的前台线程才可以退出;而对于后台线程,应用程序则足以不考虑其是否业已运行了要直白退出,所有的后台线程在应用程序退出时都见面活动终止。一般后台线程用于拍卖时比短的职责,如以一个Web服务器被得运用后台线程来处理客户端发过来的乞求信息。而前台线程一般用于拍卖要加上时待的任务,如在Web服务器受到之监听客户端请求的主次。

    这二者的分别就是:应用程序必须运行了所有的前台线程才堪退;而对后台线程,应用程序则足以免考虑其是否就运行了要一直退出,所有的后台线程在应用程序退出时犹见面自动终止。一般后台线程用于拍卖时比较短的天职,如以一个Web服务器受到得以采取后台线程来拍卖客户端发过来的求信息。而前台线程一般用于拍卖得添加日子等的职责,如以Web服务器遭受之监听客户端请求的次。

线程是依托在过程上的,进程都得了了,线程也就算没有了!

线程是寄托于经过上的,进程都结了,线程也即流失了!

若发生一个前台线程未脱,进程即使无见面停!即说的就是程序不见面倒闭!(即在资源管理器中可见见进程未终止。)

倘来一个前台线程未脱,进程不怕不见面已!即说的尽管是程序不见面倒闭!(即当资源管理器中可以看出进程未结。)

     1.3 多线程的缔造

     1.3 多线程的创

   
下面的代码创建了一个子线程,作为次的入口mian()函数所当的线程即为主线程,我们通过Thread类来创造子线程,Thread类有 ThreadStart 和
ParameterizedThreadStart类型的嘱托参数,我们吧堪一直写方法的讳。线程执行的点子可以传递参数(可选),参数的种也object,写以Start()里。

   
下面的代码创建了一个子线程,作为序的入口mian()函数所当的线程即为主线程,我们通过Thread类来创造子线程,Thread类有 ThreadStart 和
ParameterizedThreadStart类型的寄托参数,我们为堪一直写方法的讳。线程执行的方法可以传递参数(可选),参数的花色也object,写以Start()里。

opebet体育手机客户端 1

opebet体育手机客户端 2

class Program
 {
        //我们的控制台程序入口是main函数。它所在的线程即是主线程
        static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程";
            //thread.Start("王建");                       //在此方法内传递参数,类型为object,发送和接收涉及到拆装箱操作
            thread.Start(); 
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter) //方法内可以有参数,也可以没有参数
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }
  }
class Program
 {
        //我们的控制台程序入口是main函数。它所在的线程即是主线程
        static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程";
            //thread.Start("王建");                       //在此方法内传递参数,类型为object,发送和接收涉及到拆装箱操作
            thread.Start(); 
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter) //方法内可以有参数,也可以没有参数
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }
  }

opebet体育手机客户端 3

opebet体育手机客户端 4

第一使new
Thread()创建有新的线程,然后调用Start方法让线程进入就绪状态,得到系统资源后即实施,在实践进程被可能出等、休眠、死亡与堵塞四栽状态。正常执行完毕时间片后回去回到就绪状态。如果调用Suspend方法会跻身等状态,调用Sleep或者遇到进程同步使用的锁机制而眠等待。具体过程如下图所示:

首先使new
Thread()创建有新的线程,然后调用Start方法让线程进入就绪状态,得到系统资源后哪怕行,在实施过程被或许发生等、休眠、死亡与堵塞四栽状态。正常执行完毕时片后返回回到就绪状态。如果调用Suspend方法会进去待状态,调用Sleep或者遇到进程同步使用的锁机制而眠等待。具体经过如下图所示:

opebet体育手机客户端 5

opebet体育手机客户端 6

2、线程的基本操作

2、线程的基本操作

线程和另常见的类一样,有着众多性质与方法,参考下表:

线程和其它常见的接近一样,有着众多性能与方,参考下表:

opebet体育手机客户端 7

opebet体育手机客户端 8

2.1 线程的连锁属性

2.1 线程的系属性

咱们得透过地方表中的习性获取线程的局部息息相关消息,下面是代码展示暨出口结果:

咱得经者表中的性获取线程的一对系消息,下面是代码展示同出口结果:

opebet体育手机客户端 9

opebet体育手机客户端 10

static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程"; 
            thread.Start();
            StringBuilder threadInfo = new StringBuilder();
            threadInfo.Append(" 线程当前的执行状态: " + thread.IsAlive);
            threadInfo.Append("\n 线程当前的名字: " + thread.Name);
            threadInfo.Append("\n 线程当前的优先级: " + thread.Priority);
            threadInfo.Append("\n 线程当前的状态: " + thread.ThreadState);
            Console.Write(threadInfo);
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }
static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法
            thread.Name = "子线程"; 
            thread.Start();
            StringBuilder threadInfo = new StringBuilder();
            threadInfo.Append(" 线程当前的执行状态: " + thread.IsAlive);
            threadInfo.Append("\n 线程当前的名字: " + thread.Name);
            threadInfo.Append("\n 线程当前的优先级: " + thread.Priority);
            threadInfo.Append("\n 线程当前的状态: " + thread.ThreadState);
            Console.Write(threadInfo);
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("{0}开始执行。", Thread.CurrentThread.Name);
        }

opebet体育手机客户端 11

opebet体育手机客户端 12

 输输出结果: opebet体育手机客户端 13

 输输出结果: opebet体育手机客户端 14

2.2 线程的连锁操作

2.2 线程的系操作

  2.2.1 Abort()方法

  2.2.1 Abort()方法

     Abort()方法用来已线程,调用此方强制停止在实践之线程,它会扔来一个ThreadAbortException异常从而致使目标线程的住。下面代码演示:

     Abort()方法用来歇线程,调用此方强制停止在执行之线程,它见面弃来一个ThreadAbortException异常从而致使目标线程的平息。下面代码演示:

     

     

opebet体育手机客户端 15

opebet体育手机客户端 16

static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name);
            //开始终止线程
            Thread.CurrentThread.Abort();
            //下面的代码不会执行
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }
static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name);
            //开始终止线程
            Thread.CurrentThread.Abort();
            //下面的代码不会执行
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }

opebet体育手机客户端 17

opebet体育手机客户端 18

实践结果:和咱们想像的一样,下面的循环没有被执行opebet体育手机客户端 19

行结果:和我们想象的等同,下面的巡回没有为执行opebet体育手机客户端 20

 

 

  2.2.2 ResetAbort()方法

  2.2.2 ResetAbort()方法

  
   Abort方法可由此跑起ThreadAbortException异常中止线程,而用ResetAbort方法可以取消中止线程的操作,下面通过代码演示使用 ResetAbort方法。

  
   Abort方法好由此走起ThreadAbortException异常中止线程,而采取ResetAbort方法可以撤销中止线程的操作,下面通过代码演示使用 ResetAbort方法。

opebet体育手机客户端 21

opebet体育手机客户端 22

     static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            try
            {
                Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name); 
         //开始终止线程
                Thread.CurrentThread.Abort();
            }
            catch(ThreadAbortException ex)
            {
                Console.WriteLine("我是:{0},我又恢复了", Thread.CurrentThread.Name);
         //恢复被终止的线程
                Thread.ResetAbort();
            }
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }
     static void Main(string[] args)     
        {
            Thread thread = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            thread.Name = "小A";
            thread.Start();  
            Console.ReadKey();
        }

        public static void ThreadMethod(object parameter)  
        {
            try
            {
                Console.WriteLine("我是:{0},我要终止了", Thread.CurrentThread.Name); 
         //开始终止线程
                Thread.CurrentThread.Abort();
            }
            catch(ThreadAbortException ex)
            {
                Console.WriteLine("我是:{0},我又恢复了", Thread.CurrentThread.Name);
         //恢复被终止的线程
                Thread.ResetAbort();
            }
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
            }
        }

opebet体育手机客户端 23

opebet体育手机客户端 24

执行结果:opebet体育手机客户端 25

施行结果:opebet体育手机客户端 26

  2.2.3 Sleep()方法 

  2.2.3 Sleep()方法 

      
Sleep()方法调整已淤线程,是眼下线程进入休眠状态,在蛰伏过程中占有系统外存但是勿占用系统时,当休眠期以后,继续执行,声明如下:
 

      
Sleep()方法调整就淤线程,是当前线程进入休眠状态,在蛰伏过程被占有系统内存但是勿占用系统时,当休眠期之后,继续执行,声明如下:
 

        public static void Sleep(TimeSpan timeout);          //时间段
        public static void Sleep(int millisecondsTimeout);   //毫秒数
        public static void Sleep(TimeSpan timeout);          //时间段
        public static void Sleep(int millisecondsTimeout);   //毫秒数

  实例代码: 

  实例代码: 

opebet体育手机客户端 27

opebet体育手机客户端 28

       static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            threadA.Start();
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }
       static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            threadA.Start();
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }

opebet体育手机客户端 29

opebet体育手机客户端 30

用上面的代码执行以后,可以知道的观每次循环里相差300毫秒的时空。

用上面的代码执行以后,可以掌握的目每次循环中相差300毫秒的时日。

      2.2.4 join()方法

      2.2.4 join()方法

    
 Join方法主要是为此来阻塞调用线程,直到某线程终止或透过了点名时间截止。官方的解说比较平淡,通俗的说就算是开创一个子线程,给它加了此方法,其它线程就会见半途而废实施,直到这个线程执行了为止才去实践(包括主线程)。她的方法声明如下:

    
 Join方法要是故来阻塞调用线程,直到某线程终止或通过了指定时间了。官方的解说比较单调,通俗的说哪怕是创造一个子线程,给其加了这法,其它线程就会搁浅实施,直到这个线程执行完毕为止才去执行(包括主线程)。她的方式声明如下:

 public void Join();
 public bool Join(int millisecondsTimeout);    //毫秒数
 public bool Join(TimeSpan timeout);       //时间段
 public void Join();
 public bool Join(int millisecondsTimeout);    //毫秒数
 public bool Join(TimeSpan timeout);       //时间段

为了说明方面所说的,我们率先看无异段代码:  

为证明点所说之,我们先是看无异截代码:  

opebet体育手机客户端 31

opebet体育手机客户端 32

static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            Thread threadB = new Thread(ThreadMethod);     //执行的必须是无返回值的方法  
            threadB.Name = "小B";
            threadA.Start();
       //threadA.Join();      
            threadB.Start();
       //threadB.Join();

            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:主线程,我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);          //休眠300毫秒                                                
            }
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }
static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod);     //执行的必须是无返回值的方法 
            threadA.Name = "小A";
            Thread threadB = new Thread(ThreadMethod);     //执行的必须是无返回值的方法  
            threadB.Name = "小B";
            threadA.Start();
       //threadA.Join();      
            threadB.Start();
       //threadB.Join();

            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:主线程,我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);          //休眠300毫秒                                                
            }
            Console.ReadKey();
        } 
        public static void ThreadMethod(object parameter)  
        { 
            for (int i = 0; i < 10; i++)
            { 
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name,i);
                Thread.Sleep(300);         //休眠300毫秒              
            }
        }

opebet体育手机客户端 33

opebet体育手机客户端 34

 

 

坐线程之间的履行是随机的,所有执行结果以及我们想象的平,杂乱无章!但是说明她们是以履行的。opebet体育手机客户端 35

盖线程之间的行是不管三七二十一的,所有执行结果与咱们想像的同一,杂乱无章!但是说明他俩是同时履行之。opebet体育手机客户端 36

     现在我们把代码中的
 ThreadA.join()方法注释取消,首先程序中起三独线程,ThreadA、ThreadB和主线程,首先主线程先阻塞,然后线程ThreadB阻塞,ThreadA先实行,执行完毕后ThreadB接着执行,最后才是主线程执行。

     现在咱们将代码中的
 ThreadA.join()方法注释取消,首先程序中起三个线程,ThreadA、ThreadB和主线程,首先主线程先阻塞,然后线程ThreadB阻塞,ThreadA先实施,执行完毕之后ThreadB接着执行,最后才是主线程执行。

看实践结果:

圈尽结果:

opebet体育手机客户端 37

opebet体育手机客户端 38

        2.2.5 Suspent()和Resume()方法

        2.2.5 Suspent()和Resume()方法

       其实在C# 2.0以后,
Suspent()和Resume()方法已不合时宜了。suspend()方法好产生死锁。调用suspend()的时刻,目标线程会已下来,但却仍拥有在马上之前获得的锁定。此时,其他任何线程都无能够访问锁定的资源,除非叫”挂于”的线程恢复运转。对其余线程来说,如果她想过来目标线程,同时还要意欲下其它一个锁定的资源,就见面招死锁。所以无应使suspend()。

       其实在C# 2.0从此,
Suspent()和Resume()方法就不合时宜了。suspend()方法易发生死锁。调用suspend()的时节,目标线程会已下来,但可仍旧有所在就前面获得的锁定。此时,其他任何线程都不能够访问锁定的资源,除非叫”挂于”的线程恢复运转。对另外线程来说,如果它们想过来目标线程,同时以打算使任何一个锁定的资源,就见面导致死锁。所以不应该采取suspend()。

 

 

opebet体育手机客户端 39

opebet体育手机客户端 40

     static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "小A";  
            threadA.Start();  
            Thread.Sleep(3000);         //休眠3000毫秒      
            threadA.Resume();           //继续执行已经挂起的线程
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            Thread.CurrentThread.Suspend();  //挂起当前线程
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i); 
            }
        }
     static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "小A";  
            threadA.Start();  
            Thread.Sleep(3000);         //休眠3000毫秒      
            threadA.Resume();           //继续执行已经挂起的线程
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            Thread.CurrentThread.Suspend();  //挂起当前线程
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i); 
            }
        }

opebet体育手机客户端 41

opebet体育手机客户端 42

 

 

       执行方的代码。窗口并没这行
ThreadMethod方法输出循环数字,而是等了三秒钟后才输出,因为线程开始实行的下实施了Suspend()方法挂于。然后主线程休眠了3秒钟以后同时经过Resume()方法恢复了线程threadA。

       执行方的代码。窗口并没立刻行
ThreadMethod方法输出循环数字,而是等了三秒钟后才输出,因为线程开始执行的下实施了Suspend()方法挂于。然后主线程休眠了3秒钟以后同时经Resume()方法恢复了线程threadA。

    2.2.6 线程的预先级

    2.2.6 线程的预级

  如若在应用程序中生多独线程在运行,但部分线程比任何一些线程重要,这种情景下可以于一个进程中呢歧之线程指定不同的先期级。线程的先行级可以透过Thread类Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5只优先等级:AboveNormal、BelowNormal、Highest、Lowest、Normal。公共语言运行库默认是Normal类型的。见下图:

  如以应用程序中发生多单线程在运转,但部分线程比另外一对线程重要,这种状况下得当一个经过遭到也歧之线程指定不同的先期级。线程的先期级可以经Thread类Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5独先行等级:AboveNormal、BelowNormal、Highest、Lowest、Normal。公共语言运行库默认是Normal类型的。见下图:

opebet体育手机客户端 43

opebet体育手机客户端 44

一直上代码来拘禁效果:

直白上代码来拘禁作用:

opebet体育手机客户端 45

opebet体育手机客户端 46

opebet体育手机客户端 47

opebet体育手机客户端 48

static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Priority = ThreadPriority.Highest;
            threadB.Priority = ThreadPriority.BelowNormal;
            threadB.Start();
            threadA.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod(new object());
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            for (int i = 0; i < 500; i++)
            { 
                Console.Write(Thread.CurrentThread.Name); 
            }
        }
static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Priority = ThreadPriority.Highest;
            threadB.Priority = ThreadPriority.BelowNormal;
            threadB.Start();
            threadA.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod(new object());
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        {
            for (int i = 0; i < 500; i++)
            { 
                Console.Write(Thread.CurrentThread.Name); 
            }
        }

opebet体育手机客户端 49

opebet体育手机客户端 50

施行结果:

实施结果:

opebet体育手机客户端 51

opebet体育手机客户端 52

方的代码中来三单线程,threadA,threadB和主线程,threadA优先级最高,threadB优先级最低。这同碰起运行结果遭遇也得以视,线程B
偶尔会起在主线程和线程A前面。当起差不多只线程同时居于可实行状态,系统优先执行优先级较高之线程,但这只是代表优先级较高之线程占有更多之CPU时间,并无意味一定要先期实施了优先级较高的线程,才见面实行优先级较逊色之线程。

地方的代码中来三个线程,threadA,threadB和主线程,threadA优先级最高,threadB优先级最低。这同触及由运行结果遭遇呢足以看,线程B
偶尔会面世于主线程和线程A前面。当有多单线程同时处于可实施状态,系统优先履优先级较高之线程,但立刻只有象征优先级较高的线程占有更多之CPU时间,并无意味一定要是先实行了优先级较高之线程,才见面执行优先级较逊色之线程。

事先级更强意味着CPU分配受该线程的光阴片越多,执行时间便差不多

先期级更强意味着CPU分配为该线程的年月片越多,执行时间哪怕基本上

预先级更没有表示CPU分配为该线程的辰片越少,执行时间便掉

先行级更低表示CPU分配给该线程的时日片越少,执行时哪怕少

   3、线程同步

   3、线程同步

  什么是线程安全:

  什么是线程安全:

  线程安全是据在当一个线程访问该类的某数常常,进行维护,其他线程不可知展开走访直到该线程读取了,其他线程才不过运。不见面并发数未同等或数额传。

  线程安全是因于当一个线程访问该类的某部数常常,进行维护,其他线程不可知进行访问直到该线程读取完,其他线程才可使。不会见面世数量不平等或者数传。

   线程有或同其它线程共享有资源,比如,内存,文件,数据库等。当多单线程同时读写及同份共享资源的时段,可能会见滋生冲突。这时候,我们得引入线程“同步”机制,即诸君线程之间要产生只先行来晚至,不可知同一卷蜂挤上去抢作一团。线程同步的真正意思和字面意思恰好相反。线程同步的实事求是意思,其实是“排队”:几只线程之间要排队,一个一个对共享资源进行操作,而休是还要进行操作。

   线程有或同其他线程共享有资源,比如,内存,文件,数据库等。当多个线程同时读写及同卖共享资源的时段,可能会见惹冲突。这时候,我们用引入线程“同步”机制,即诸君线程之间一旦生只先行来后到,不克同一窝蜂挤上去抢作一团。线程同步的忠实意思和字面意思恰好相反。线程同步的实在意思,其实是“排队”:几只线程之间一旦排队,一个一个对共享资源进行操作,而未是还要拓展操作。

为什么要兑现并啊,下面的事例我们拿著名的单例模式吧吧。看代码

怎么要促成同台啊,下面的例子我们用著名的单例模式吧吧。看代码

opebet体育手机客户端 53

opebet体育手机客户端 54

public class Singleton
    {
        private static Singleton instance; 
        private Singleton()   //私有函数,防止实例
        {

        } 
        public static Singleton GetInstance()
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
public class Singleton
    {
        private static Singleton instance; 
        private Singleton()   //私有函数,防止实例
        {

        } 
        public static Singleton GetInstance()
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }

opebet体育手机客户端 55

opebet体育手机客户端 56

     
 单例模式就是是包在全部应用程序的生命周期中,在任何时刻,被指定的接近就来一个实例,并也客户程序提供一个赢得该实例的全局访问点。但地方代码来一个显的问题,那就算是如果两单线程同时失去得之目标实例,那。。。。。。。。

     
 单例模式就是是保证在周应用程序的生命周期中,在任何时刻,被指定的近乎才发一个实例,并为客户程序提供一个取得该实例的大局访问点。但地方代码有一个肯定的问题,那就是是若两单线程同时失去得到这目标实例,那。。。。。。。。

我们队代码进行修改:

咱帮代码进行修改:

opebet体育手机客户端 57

opebet体育手机客户端 58

public class Singleton
{
       private static Singleton instance;
       private static object obj=new object(); 
       private Singleton()        //私有化构造函数
       {

       } 
       public static Singleton GetInstance()
       {
               if(instance==null)
               {
                      lock(obj)      //通过Lock关键字实现同步
                      {
                             if(instance==null)
                             {
                                     instance=new Singleton();
                             }
                      }
               }
               return instance;
       }
}
public class Singleton
{
       private static Singleton instance;
       private static object obj=new object(); 
       private Singleton()        //私有化构造函数
       {

       } 
       public static Singleton GetInstance()
       {
               if(instance==null)
               {
                      lock(obj)      //通过Lock关键字实现同步
                      {
                             if(instance==null)
                             {
                                     instance=new Singleton();
                             }
                      }
               }
               return instance;
       }
}

opebet体育手机客户端 59

opebet体育手机客户端 60

透过修改后的代码。加了一个
lock(obj)代码块。这样就是可知实现并了,假如不是坏明白的话语,咱们看后面继续教授~

通过修改后的代码。加了一个
lock(obj)代码块。这样就算会实现协同了,假如不是充分了解的说话,咱们看后面继续教授~

  3.0 使用Lock关键字贯彻线程同步 

  3.0 使用Lock关键字贯彻线程同步 

  首先创建两单线程,两只线程执行和一个措施,参考下面的代码:

  先是创建两个线程,两单线程执行和一个方法,参考下面的代码:

opebet体育手机客户端 61

opebet体育手机客户端 62

static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        { 
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);
            }
        }
static void Main(string[] args)
        {
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public static void ThreadMethod(object parameter)
        { 
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                Thread.Sleep(300);
            }
        }

opebet体育手机客户端 63

opebet体育手机客户端 64

施行结果:

施行结果:

opebet体育手机客户端 65

opebet体育手机客户端 66

 

 

经者的履结果,可以老懂的观,两个线程是以又履行ThreadMethod这个方式,这眼看不符合我们线程同步的渴求。我们对代码进行改动如下:

通过地方的实践结果,可以好懂的来看,两个线程是在又施行ThreadMethod这个方式,这明确不称我们线程同步的要求。我们对代码进行改动如下:

opebet体育手机客户端 67

opebet体育手机客户端 68

opebet体育手机客户端 69

opebet体育手机客户端 70

static void Main(string[] args)
        {
            Program pro = new Program();
            Thread threadA = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)             //添加lock关键字
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            } 
        }
static void Main(string[] args)
        {
            Program pro = new Program();
            Thread threadA = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)             //添加lock关键字
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            } 
        }

opebet体育手机客户端 71

opebet体育手机客户端 72

履行结果:

履行结果:

opebet体育手机客户端 73

opebet体育手机客户端 74

咱经过补加了 lock(this)
{…}代码,查看执行结果实现了俺们想只要之线程同步要求。但是我们了解this表示手上好像实例的自家,那么闹如此一种植状况,我们拿要看的不二法门所在的色进行简单单实例A和B,线程A看实例A的方法ThreadMethod,线程B访问实例B的法子ThreadMethod,这样的话还能上线程同步的急需也。

咱由此补偿加了 lock(this)
{…}代码,查看执行结果实现了咱纪念使的线程同步要求。但是咱领略this表示即好像实例的自己,那么来这么一栽状况,我们将需要看的不二法门所在的色进行有限个实例A和B,线程A看实例A的方法ThreadMethod,线程B访问实例B的方法ThreadMethod,这样的话还能达成线程同步的要求为。

opebet体育手机客户端 75

opebet体育手机客户端 76

opebet体育手机客户端 77

opebet体育手机客户端 78

static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }
static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (this)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }

opebet体育手机客户端 79

opebet体育手机客户端 80

履行结果:

执行结果:

opebet体育手机客户端 81

opebet体育手机客户端 82

我们会意识,线程又无实现并了!lock(this)对于这种状态是深的!所以需要我们本着代码进行改动!修改后底代码如下: 

咱们见面发觉,线程又没有兑现并了!lock(this)对于这种情形是死的!所以用我们针对代码进行改动!修改后的代码如下: 

opebet体育手机客户端 83

opebet体育手机客户端 84

opebet体育手机客户端 85

opebet体育手机客户端 86

private static object obj = new object();
        static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }
private static object obj = new object();
        static void Main(string[] args)
        {
            Program pro1 = new Program();                    
            Program pro2 = new Program();                   
            Thread threadA = new Thread(pro1.ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "王文建";
            Thread threadB = new Thread(pro2.ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "生旭鹏";
            threadA.Start();
            threadB.Start();
            Console.ReadKey();
        }
        public void ThreadMethod(object parameter)
        {
            lock (obj)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("我是:{0},我循环{1}次", Thread.CurrentThread.Name, i);
                    Thread.Sleep(300);
                }
            }
        }

opebet体育手机客户端 87

opebet体育手机客户端 88

透过翻执行结果。会发现代码实现了我们的要求。那么 lock(this)
和lock(Obj)有什么分别吧? 

由此翻看执行结果。会发现代码实现了咱的要求。那么 lock(this)
和lock(Obj)有啊区别为? 

lock(this) 锁定 当前实例对象,如果有多个类实例的话,lock锁定的只是当前类实例,对其它类实例无影响。所有不推荐使用。 
lock(typeof(Model))锁定的是model类的所有实例。 
lock(obj)锁定的对象是全局的私有化静态变量。外部无法对该变量进行访问。 
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 
所以,lock的结果好不好,还是关键看锁的谁,如果外边能对这个谁进行修改,lock就失去了作用。所以一般情况下,使用私有的、静态的并且是只读的对象。
lock(this) 锁定 当前实例对象,如果有多个类实例的话,lock锁定的只是当前类实例,对其它类实例无影响。所有不推荐使用。 
lock(typeof(Model))锁定的是model类的所有实例。 
lock(obj)锁定的对象是全局的私有化静态变量。外部无法对该变量进行访问。 
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 
所以,lock的结果好不好,还是关键看锁的谁,如果外边能对这个谁进行修改,lock就失去了作用。所以一般情况下,使用私有的、静态的并且是只读的对象。

总结:

总结:

1、lock的是必是引用类型的对象,string类型除外。

1、lock的凡要是援类型的对象,string类型除外。

2、lock推荐的做法是运静态的、只读的、私有的目标。

2、lock推荐的做法是动静态的、只念的、私有的目标。

3、保证lock的对象在表无法修改才发出含义,如果lock的靶子在外表改变了,对另外线程就会见通行,失去了lock的含义。

3、保证lock的目标在外表无法修改才发含义,如果lock的对象在表改变了,对另线程就会见通行,失去了lock的义。

*     不能够锁定字符串,锁得字符串尤其危险,因为字符串被集体语言运行库
(CLR)“暂留”。
这表示整个程序中另外给定字符串都单出一个实例,就是立即同一个对象表示了有运行的应用程序域的有着线程中之拖欠文件。因此,只要在应用程序进程中之别岗位处在拥有同样内容的字符串上停了锁,就将锁定应用程序中该字符串的保有实例。通常,最好避免锁定
public
类型或锁定不让应用程序控制的对象实例。例如,如果该实例可以给公开访问,则
lock(this)
可能会见生问题,因为无受控制的代码也说不定会见锁定该目标。这或导致死锁,即有限单或重复多只线程等待释放同一对象。出于同样的来头,锁定公共数据类型(相比于对象)也或导致问题。而且lock(this)只对眼前目标中,如果多独对象期间就达成不顶一起的力量。lock(typeof(Class))与锁定字符串一样,范围最普遍了。*

*     不克锁定字符串,锁得字符串尤其危险,因为字符串被集体语言运行库
(CLR)“暂留”。
这表示整个程序中任何给定字符串都只有来一个实例,就是就和一个目标表示了颇具运行的应用程序域的备线程中之欠公文。因此,只要在应用程序进程中之别样位置处于拥有同样内容的字符串上停放了锁,就拿锁定应用程序中该字符串的具有实例。通常,最好避免锁定
public
类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以叫公开访问,则
lock(this)
可能会见生问题,因为不让控制的代码也说不定会见锁定该对象。这恐怕导致死锁,即有限只或重新多只线程等待释放同一对象。出于同样的因,锁定公共数据类型(相比叫对象)也或导致问题。而且lock(this)只对脚下目标中,如果多个目标期间便上不顶一块儿的功能。lock(typeof(Class))与锁定字符串一样,范围最常见了。*

  3.1 使用Monitor类实现线程同步      

  3.1 使用Monitor类实现线程同步      

     
Lock关键字是Monitor的均等种植替换用法,lock在IL代码中会于翻成Monitor. 

     
Lock关键字是Monitor的同一种替换用法,lock于IL代码中会叫翻成Monitor. 

     lock(obj)

     lock(obj)

              {
                 //代码段
             } 
    就相同于 
    Monitor.Enter(obj); 
                //代码段
    Monitor.Exit(obj);  

              {
                 //代码段
             } 
    就同于 
    Monitor.Enter(obj); 
                //代码段
    Monitor.Exit(obj);  

           Monitor的常用属性和方:

           Monitor的常用属性和道:

    Enter(Object) 在指定对象上博排异锁。

    Enter(Object) 在指定对象上沾排异锁。

    Exit(Object) 释放指定对象上的破除异锁。 

    Exit(Object) 释放指定对象上的清除异锁。 

 

 

    Pulse 通知等队列中的线程锁定目标状态的改变。

    Pulse 通知等队列中的线程锁定目标状态的更动。

    PulseAll 通知所有的守候线程对象状态的改动。

    PulseAll 通知所有的等候线程对象状态的改。

    TryEnter(Object) 试图获取指定对象的消除他锁。

    TryEnter(Object) 试图获取指定对象的铲除异锁。

    TryEnter(Object,
Boolean)
 尝试获得指定对象上之排除他锁,并机关安装一个价,指示是否收获了该锁。

    TryEnter(Object,
Boolean)
 尝试获得指定对象及之排他锁,并活动安装一个值,指示是否收获了该锁。

    Wait(Object) 释放对象上的锁并阻止当前线程,直到其再也取得该锁。

    Wait(Object) 释放对象及之锁并阻止当前线程,直到其重赢得该锁。

     
常用的艺术发生半点单,Monitor.Enter(object)方法是赢得锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用之简单单道,在动过程中以避免获取锁之后以那个,致锁无法自由,所以用以try{}
catch(){}之后的finally{}结构体中放出锁(Monitor.Exit())。

     
常用的道有三三两两只,Monitor.Enter(object)方法是得锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用之简单单艺术,在动过程遭到以避免获取锁之后因生,致锁无法自由,所以待以try{}
catch(){}之后的finally{}结构体中放出锁(Monitor.Exit())。

Enter(Object)的用法很简短,看代码 

Enter(Object)的用法很粗略,看代码 

opebet体育手机客户端 89

opebet体育手机客户端 90

     static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            Monitor.Enter(obj);      //Monitor.Enter(obj)  锁定对象
            try
            {
                for (int i = 0; i < 500; i++)
                {
                    Console.Write(Thread.CurrentThread.Name); 
                }
            }
            catch(Exception ex){   }
            finally
            { 
                Monitor.Exit(obj);  //释放对象
            } 
        } 
     static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            Monitor.Enter(obj);      //Monitor.Enter(obj)  锁定对象
            try
            {
                for (int i = 0; i < 500; i++)
                {
                    Console.Write(Thread.CurrentThread.Name); 
                }
            }
            catch(Exception ex){   }
            finally
            { 
                Monitor.Exit(obj);  //释放对象
            } 
        } 

opebet体育手机客户端 91

opebet体育手机客户端 92

 

 

TryEnter(Object)TryEnter() 方法以尝获得一个目标上的显式锁方面跟
Enter()
方法类似。然而,它不像Enter()方法那样会卡住执行。如果线程成功跻身关键区域那么TryEnter()方法会返回true. 和准备拿走指定对象的铲除异锁。看下面代码演示:

TryEnter(Object)TryEnter() 方法在尝试取一个对象及之显式锁方面与
Enter()
方法类似。然而,它不像Enter()方法那样会死执行。如果线程成功进入重点区域那么TryEnter()方法会返回true. 和计算取指定对象的消除他锁。看下代码演示:

      我们得以经过Monitor.TryEnter(monster,
1000),该法吧会避免死锁的发出,我们下面的事例用到的凡该方式的重载,Monitor.TryEnter(Object,Int32),。 

      我们得经Monitor.TryEnter(monster,
1000),该措施为能避免死锁的发生,我们下的例子用到之是拖欠办法的重载,Monitor.TryEnter(Object,Int32),。 

opebet体育手机客户端 93

opebet体育手机客户端 94

static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            bool flag = Monitor.TryEnter(obj, 1000);   //设置1S的超时时间,如果在1S之内没有获得同步锁,则返回false
        //上面的代码设置了锁定超时时间为1秒,也就是说,在1秒中后,
       //lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁
            try
            {
                if (flag)
                {
                    for (int i = 0; i < 500; i++)
                    {
                        Console.Write(Thread.CurrentThread.Name); 
                    }
                }
            }
            catch(Exception ex)
            {

            }
            finally
            {
                if (flag)
                    Monitor.Exit(obj);
            } 
        } 
static void Main(string[] args)
        {                
            Thread threadA = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadA.Name = "A";
            Thread threadB = new Thread(ThreadMethod); //执行的必须是无返回值的方法 
            threadB.Name = "B";
            threadA.Start();
            threadB.Start();
            Thread.CurrentThread.Name = "C";
            ThreadMethod();
            Console.ReadKey();
        }
        static object obj = new object();
        public static void ThreadMethod()
        {
            bool flag = Monitor.TryEnter(obj, 1000);   //设置1S的超时时间,如果在1S之内没有获得同步锁,则返回false
        //上面的代码设置了锁定超时时间为1秒,也就是说,在1秒中后,
       //lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁
            try
            {
                if (flag)
                {
                    for (int i = 0; i < 500; i++)
                    {
                        Console.Write(Thread.CurrentThread.Name); 
                    }
                }
            }
            catch(Exception ex)
            {

            }
            finally
            {
                if (flag)
                    Monitor.Exit(obj);
            } 
        } 

opebet体育手机客户端 95

opebet体育手机客户端 96

 Monitor.Wait和Monitor()Pause()

 Monitor.Wait和Monitor()Pause()

Wait(object)方法:释放对象上的锁并阻止当前线程,直到它再也得到该锁,该线程进入等队列。
 Pulse方法:只有锁的即主人可以采取 Pulse 向等待对象发出信号,当前所有指定对象上的吊之线程调用此道以便向行中的生一个线程发出锁之信号。接收及脉冲后,等待线程就为活动至即绪队列中。在调用 Pulse 的线程释放锁后,就绪队列中之下一个线程(不必然是收到至脉冲的线程)将收获该锁。
另外

Wait(object)方法:释放对象及之锁并阻止当前线程,直到其又赢得该锁,该线程进入待队列。
 Pulse方法:只有锁之此时此刻主人可以以 Pulse 向等待对象发出信号,当前有所指定对象及之沿的线程调用此措施以便向行中之产一个线程发出锁的信号。接收到脉冲后,等待线程就吃移位至就绪队列中。在调用 Pulse 的线程释放锁后,就绪队列中的生一个线程(不自然是接到及脉冲的线程)将赢得该锁。
另外

        Wait 和 Pulse 方法要写于 Monitor.Enter
和Moniter.Exit 之间。

        Wait 和 Pulse 方法要写在 Monitor.Enter
和Moniter.Exit 之间。

面是MSDN的解说。不知晓看代码:

上面是MSDN的说明。不理解看代码:

 首先我们定义一个攻击类,

 首先我们定义一个攻击类,

opebet体育手机客户端 97

opebet体育手机客户端 98

/// <summary>
    /// 怪物类
    /// </summary>
    internal class Monster
    {
        public int Blood { get; set; }
        public Monster(int blood)
        {
            this.Blood = blood;
            Console.WriteLine("我是怪物,我有{0}滴血",blood);
        }
    }
/// <summary>
    /// 怪物类
    /// </summary>
    internal class Monster
    {
        public int Blood { get; set; }
        public Monster(int blood)
        {
            this.Blood = blood;
            Console.WriteLine("我是怪物,我有{0}滴血",blood);
        }
    }

opebet体育手机客户端 99

opebet体育手机客户端 100

接下来于概念一个攻击类

然后以概念一个攻击类

opebet体育手机客户端 101

opebet体育手机客户端 102

/// <summary>
    /// 攻击类
    /// </summary>
    internal class Play
    {
        /// <summary>
        /// 攻击者名字
        /// </summary>
        public string Name { get; set; } 
        /// <summary>
        /// 攻击力
        /// </summary>
        public int Power{ get; set; }
        /// <summary>
        /// 法术攻击
        /// </summary>
        public void magicExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood>0)
            {
                Monitor.Wait(monster);
                Console.WriteLine("当前英雄:{0},正在使用法术攻击打击怪物", this.Name);
                if(m.Blood>= Power)
                {
                    m.Blood -= Power;
                }
                else
                {
                    m.Blood = 0;
                }
                Thread.Sleep(300);
                Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                Monitor.PulseAll(monster);
            }
            Monitor.Exit(monster);
        }
        /// <summary>
        /// 物理攻击
        /// </summary>
        /// <param name="monster"></param>
        public void physicsExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood > 0)
            {
                Monitor.PulseAll(monster);
                if (Monitor.Wait(monster, 1000))     //非常关键的一句代码
                {
                    Console.WriteLine("当前英雄:{0},正在使用物理攻击打击怪物", this.Name);
                    if (m.Blood >= Power)
                    {
                        m.Blood -= Power;
                    }
                    else
                    {
                        m.Blood = 0;
                    }
                    Thread.Sleep(300);
                    Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                }
            }
            Monitor.Exit(monster);
        }
    }
/// <summary>
    /// 攻击类
    /// </summary>
    internal class Play
    {
        /// <summary>
        /// 攻击者名字
        /// </summary>
        public string Name { get; set; } 
        /// <summary>
        /// 攻击力
        /// </summary>
        public int Power{ get; set; }
        /// <summary>
        /// 法术攻击
        /// </summary>
        public void magicExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood>0)
            {
                Monitor.Wait(monster);
                Console.WriteLine("当前英雄:{0},正在使用法术攻击打击怪物", this.Name);
                if(m.Blood>= Power)
                {
                    m.Blood -= Power;
                }
                else
                {
                    m.Blood = 0;
                }
                Thread.Sleep(300);
                Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                Monitor.PulseAll(monster);
            }
            Monitor.Exit(monster);
        }
        /// <summary>
        /// 物理攻击
        /// </summary>
        /// <param name="monster"></param>
        public void physicsExecute(object monster)
        {
            Monster m = monster as Monster;
            Monitor.Enter(monster);
            while (m.Blood > 0)
            {
                Monitor.PulseAll(monster);
                if (Monitor.Wait(monster, 1000))     //非常关键的一句代码
                {
                    Console.WriteLine("当前英雄:{0},正在使用物理攻击打击怪物", this.Name);
                    if (m.Blood >= Power)
                    {
                        m.Blood -= Power;
                    }
                    else
                    {
                        m.Blood = 0;
                    }
                    Thread.Sleep(300);
                    Console.WriteLine("怪物的血量还剩下{0}", m.Blood);
                }
            }
            Monitor.Exit(monster);
        }
    }

opebet体育手机客户端 103

opebet体育手机客户端 104

实践代码:

实践代码:

opebet体育手机客户端 105

opebet体育手机客户端 106

    static void Main(string[] args)
        {
            //怪物类
            Monster monster = new Monster(1000);
            //物理攻击类
            Play play1 = new Play() { Name = "无敌剑圣", Power = 100 };
            //魔法攻击类
            Play play2 = new Play() { Name = "流浪法师", Power = 120 };
            Thread thread_first = new Thread(play1.physicsExecute);    //物理攻击线程
            Thread thread_second = new Thread(play2.magicExecute);     //魔法攻击线程
            thread_first.Start(monster);
            thread_second.Start(monster);
            Console.ReadKey();
        }
    static void Main(string[] args)
        {
            //怪物类
            Monster monster = new Monster(1000);
            //物理攻击类
            Play play1 = new Play() { Name = "无敌剑圣", Power = 100 };
            //魔法攻击类
            Play play2 = new Play() { Name = "流浪法师", Power = 120 };
            Thread thread_first = new Thread(play1.physicsExecute);    //物理攻击线程
            Thread thread_second = new Thread(play2.magicExecute);     //魔法攻击线程
            thread_first.Start(monster);
            thread_second.Start(monster);
            Console.ReadKey();
        }

opebet体育手机客户端 107

opebet体育手机客户端 108

出口结果:

出口结果:

opebet体育手机客户端 109

opebet体育手机客户端 110

总结:

总结:

  首先栽状态:

  率先种植情景:

  1. thread_first首先获得同对象的锁,当行及 Monitor.Wait(monster);时,thread_first线程释放自己对一头对象的吊,流放自己及等候队列,直到自己再次取得锁,否则一直不通。
  2. 而thread_second线程一开始就竞争并锁所以处于就绪队列中,这时候thread_second直接打稳妥队列出来获得了monster对象锁,开始执行到Monitor.PulseAll(monster)时,发送了个Pulse信号。
  3. 这时候thread_first接收到信号进入到妥善状态。然后thread_second继续往生实行及
    Monitor.Wait(monster,
    1000)时,这是同样句很主要之代码,thread_second将自己放到等候队列并释放自我对同步锁的垄断,该待安装了1S之超时值,当B线程在1S中没有再赢得到锁自动添加到妥善队列。
  4. 这时thread_first从Monitor.Wait(monster)的围堵了,返回true。开始实践、打印。执行下一行的Monitor.Pulse(monster),这时候thread_second假如1S底日还未曾过,thread_second接收至信号,于是将协调加加至妥善队列。
  5. thread_first的共同代码块了后,thread_second再次取得执行权, Monitor.Wait(m_smplQueue,
    1000)返回true,于是连续于该代码处往下执行、打印。当还实施及Monitor.Wait(monster,
    1000),又起了步骤3。
  6. 次第轮回。。。。
  1. thread_first首先取得同对象的沿,当尽到 Monitor.Wait(monster);时,thread_first线程释放自己对联合对象的沿,流放自己及等候队列,直到好又获得锁,否则一直不通。
  2. 而thread_second线程一开始就是竞争并锁所以处于就绪队列中,这时候thread_second直接由稳队列出来获得了monster对象锁,开始推行及Monitor.PulseAll(monster)时,发送了只Pulse信号。
  3. 这时候thread_first接收及信号进入及妥善状态。然后thread_second继续朝生执行及
    Monitor.Wait(monster,
    1000)时,这是同等句很关键之代码,thread_second将团结放逐到等候队列并释放自身对同步锁的霸,该等安装了1S底超时值,当B线程在1S之内没有更获得到锁自动添加到妥善队列。
  4. 这时thread_first从Monitor.Wait(monster)的死了,返回true。开始施行、打印。执行下一行的Monitor.Pulse(monster),这时候thread_second假如1S之辰还尚无了,thread_second接收及信号,于是以团结补加至妥善队列。
  5. thread_first的联合代码块了后,thread_second再次得到执行权, Monitor.Wait(m_smplQueue,
    1000)返回true,于是继续从该代码处往生执行、打印。当还实施到Monitor.Wait(monster,
    1000),又开了步骤3。
  6. 逐循环。。。。

 
 其次栽情形:thread_second首先取得同锁对象,首先实施及Monitor.PulseAll(monster),因为程序中并未得拭目以待信号进入就绪状态的线程,所以这无异于句代码没有意义,当尽及 Monitor.Wait(monster,
1000),自动将团结配到等候队列并以此间阻塞,1S
时间过后thread_second自动添加至妥善队列,线程thread_first获得monster对象锁,执行及Monitor.Wait(monster);时起阻塞释放并对象锁,线程thread_second执行,执行Monitor.PulseAll(monster)时通知thread_first。于是又起来率先种情况…

 
 其次种状态:thread_second首先得到同锁对象,首先实施到Monitor.PulseAll(monster),因为程序中莫要拭目以待信号进入就绪状态的线程,所以这无异于句子代码没有意义,当执行到 Monitor.Wait(monster,
1000),自动将自己放到等候队列并在此地阻塞,1S
时间之后thread_second自动添加到妥善队列,线程thread_first获得monster对象锁,执行及Monitor.Wait(monster);时起堵塞释放并对象锁,线程thread_second执行,执行Monitor.PulseAll(monster)时通知thread_first。于是又开率先种植情况…

Monitor.Wait是深受眼前进程睡眠在薄资源上连释放独占锁,它只是等待,并无脱离,当等了,就要继续执行剩下的代码。

Monitor.Wait是于眼前历程睡眠在薄资源达到连释放独占锁,它只是等待,并无离,当等了,就要继续执行剩下的代码。

 

 

  3.0 使用Mutex类实现线程同步

  3.0 使用Mutex类实现线程同步

   
  Mutex的暴特色是可以跨应用程序域边界对资源开展垄断访问,即好用于共同不同进程被的线程,这种功能本来这是坐牺牲更多的系统资源为代价的。

   
  Mutex的突出特点是好跨应用程序域边界对资源进行垄断访问,即好用来共同不同进程被的线程,这种作用本来这是为献身更多的系统资源为代价的。

  主要常用之片单主意:

  主要常用之有限只章程:

 public virtual bool WaitOne()   阻止当前线程,直到当前
System.Threading.WaitHandle 收到信号获取互斥锁。

 public virtual bool WaitOne()   阻止当前线程,直到目前
System.Threading.WaitHandle 收到信号获取互斥锁。

 public void ReleaseMutex()     释放 System.Threading.Mutex 一次。

 public void ReleaseMutex()     释放 System.Threading.Mutex 一次。

  使用实例:

  使用实例:

opebet体育手机客户端 111

opebet体育手机客户端 112

    static void Main(string[] args)
        {
            Thread[] thread = new Thread[3];
            for (int i = 0; i < 3; i++)
            {
                thread[i] = new Thread(ThreadMethod1);
                thread[i].Name = i.ToString();
            }
            for (int i = 0; i < 3; i++)
            {
                thread[i].Start();
            }
            Console.ReadKey(); 
        } 

        public static void ThreadMethod1(object val)
        {
            mutet.WaitOne();    //获取锁
            for (int i = 0; i < 500; i++)
            {
                Console.Write(Thread.CurrentThread.Name); 
            } 
            mutet.ReleaseMutex();  //释放锁
        }
    static void Main(string[] args)
        {
            Thread[] thread = new Thread[3];
            for (int i = 0; i < 3; i++)
            {
                thread[i] = new Thread(ThreadMethod1);
                thread[i].Name = i.ToString();
            }
            for (int i = 0; i < 3; i++)
            {
                thread[i].Start();
            }
            Console.ReadKey(); 
        } 

        public static void ThreadMethod1(object val)
        {
            mutet.WaitOne();    //获取锁
            for (int i = 0; i < 500; i++)
            {
                Console.Write(Thread.CurrentThread.Name); 
            } 
            mutet.ReleaseMutex();  //释放锁
        }

opebet体育手机客户端 113

opebet体育手机客户端 114

 2、线程池

 2、线程池

   
  上面介绍了介绍了平时运的大多数的多线程的例子,但以骨子里开发中采取的线程往往是大度的和更加复杂的,这时,每次都创造线程、启动线程。从性质及来讲,这样做并无佳(因为各个用一个线程就要创建一个,需要占用系统出);从操作上来讲,每次都使启动,比较费心。为是引入的线程池的概念。

   
  上面介绍了介绍了平时采取的多数的多线程的事例,但于骨子里支出被动用的线程往往是大量底和更加复杂的,这时,每次都创线程、启动线程。从性质及来讲,这样做并无精彩(因为各使用一个线程就要创建一个,需要占用系统出);从操作及来讲,每次都如开动,比较累。为这引入的线程池的定义。

  好处:

  好处:

  1.压缩在创建及销毁线程上所花的辰以及系统资源的开销 
 
2.假设无使用线程池,有或造成系统创造大气线程而致使消耗了系统内存和”过度切换”。

  1.精减在创立及销毁线程上所消费的时光与系统资源的开销 
 
2.而无使用线程池,有或造成系统创造大气线程而造成消耗了系统内存和”过度切换”。

于啊情形下使用线程池? 

当啊状态下使用线程池? 

    1.么任务处理的时空比短 
    2.消处理的天职的数目大 

    1.单个任务处理的工夫比短 
    2.得处理的任务的多寡大 

线程池最多管理线程数量=“处理器数 *
250”。也就是说,如果您的机器也2独2核CPU,那么CLR线程池的容量默认上限便是1000

线程池最多管理线程数量=“处理器数 *
250”。也就是说,如果你的机器也2只2核CPU,那么CLR线程池的容量默认上限便是1000

透过线程池创建的线程默认为后台线程,优先级默认为Normal。

通过线程池创建的线程默认为后台线程,优先级默认为Normal。

代码示例:

代码示例:

opebet体育手机客户端 115

opebet体育手机客户端 116

    static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod1), new object());    //参数可选
            Console.ReadKey();
        }

        public static void ThreadMethod1(object val)
        { 
            for (int i = 0; i <= 500000000; i++)
            {
                if (i % 1000000 == 0)
                {
                    Console.Write(Thread.CurrentThread.Name);
                } 
            } 
        }
    static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod1), new object());    //参数可选
            Console.ReadKey();
        }

        public static void ThreadMethod1(object val)
        { 
            for (int i = 0; i <= 500000000; i++)
            {
                if (i % 1000000 == 0)
                {
                    Console.Write(Thread.CurrentThread.Name);
                } 
            } 
        }

opebet体育手机客户端 117

opebet体育手机客户端 118

 

 

 

 

至于线程池的诠释请参考:

关于线程池的解释请参见:

http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html

http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html

标签:,

Your Comments

近期评论

    功能


    网站地图xml地图