亚洲必赢手机多线程和线程池,C

by admin on 2018年12月14日

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()里。

亚洲必赢手机 1

亚洲必赢手机 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);
        }
  }

亚洲必赢手机 3

亚洲必赢手机 4

首先采纳new
Thread()创建有新的线程,然后调用Start方法教线程进入就绪状态,得到系统资源后便实施,在尽进程被可能出等、休眠、死亡与堵塞四栽状态。正常执行了时片后回回到就绪状态。假诺调用Suspend方法会进去待状态,调用Sleep或者碰着进程同步使用的锁机制而眠等待。具体经过如下图所示:

第一采纳new
Thread()成立有新的线程,然后调用Start方法让线程进入就绪状态,得到系统资源后就行,在实践进程遭到或许发生等、休眠、死亡和堵塞四种状态。正常履行完毕时间片后回来回到就绪状态。要是调用Suspend方法会进去等状态,调用Sleep或者遭逢进程同步使用的锁机制而眠等待。具体过程如下图所示:

亚洲必赢手机 5

亚洲必赢手机 6

2、线程的基本操作

2、线程的基本操作

线程和其他常见的好像一样,有着许多特性和方,参考下表:

线程和外常见的类似一样,有着广大性质和艺术,参考下表:

亚洲必赢手机 7

亚洲必赢手机 8

2.1 线程的相关属性

2.1 线程的相干属性

我们可以通过地点表中的性能获取线程的一部分有关音信,下边是代码体现以及输出结果:

我们可以通过者表中的属性获取线程的有些连锁音信,下面是代码显示及出口结果:

亚洲必赢手机 9

亚洲必赢手机 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);
        }

亚洲必赢手机 11

亚洲必赢手机 12

 输输出结果: 亚洲必赢手机 13

 输输出结果: 亚洲必赢手机 14

2.2 线程的连带操作

2.2 线程的连锁操作

  2.2.1 Abort()方法

  2.2.1 Abort()方法

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

     Abort()方法用来歇线程,调用此道强制截止在执行的线程,它相会弃来一个ThreadAbortException非常从而造成目的线程的平息。下边代码演示:

     

亚洲必赢手机,     

亚洲必赢手机 15

亚洲必赢手机 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);
            }
        }

亚洲必赢手机 17

亚洲必赢手机 18

施行结果:和我们想象的一律,下面的轮回没有叫实施亚洲必赢手机 19

履结果:和我们想象的同等,下面的轮回没有于实施亚洲必赢手机 20

 

 

  2.2.2 ResetAbort()方法

  2.2.2 ResetAbort()方法

  
   Abort方法好经跑起ThreadAbortException分外中止线程,而使ResetAbort方法可收回中止线程的操作,下边通过代码演示使用 ResetAbort方法。

  
   Abort方法好透过跑起ThreadAbortException分外中止线程,而采纳ResetAbort方法可收回中止线程的操作,下面通过代码演示使用 ResetAbort方法。

亚洲必赢手机 21

亚洲必赢手机 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);
            }
        }

亚洲必赢手机 23

亚洲必赢手机 24

履行结果:亚洲必赢手机 25

执行结果:亚洲必赢手机 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);   //毫秒数

  实例代码: 

  实例代码: 

亚洲必赢手机 27

亚洲必赢手机 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毫秒              
            }
        }

亚洲必赢手机 29

亚洲必赢手机 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);       //时间段

为验证方面所说的,我们率先看同样段代码:  

为了求证方面所说的,我们首先看一样段代码:  

亚洲必赢手机 31

亚洲必赢手机 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毫秒              
            }
        }

亚洲必赢手机 33

亚洲必赢手机 34

 

 

以线程之间的施行是轻易的,所有执行结果和我们想像的同样,杂乱无章!不过表明他们是还要推行之。亚洲必赢手机 35

坐线程之间的举办是自由的,所有执行结果跟我们想象的同等,杂乱无章!然而表达她们是又履行的。亚洲必赢手机 36

     现在我们管代码中之
 ThreadA.join()方法注释裁撤,首先程序中发出三单线程,ThreadA、ThreadB和主线程,首先主线程先阻塞,然后线程ThreadB阻塞,ThreadA先进行,执行完毕之后ThreadB接着执行,最终才是主线程执行。

     现在我们把代码中之
 ThreadA.join()方法注释撤消,首先程序中生出三独线程,ThreadA、ThreadB和主线程,首先主线程先阻塞,然后线程ThreadB阻塞,ThreadA先进行,执行了后ThreadB接着执行,最终才是主线程执行。

关押执行结果:

在押尽结果:

亚洲必赢手机 37

亚洲必赢手机 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()。

 

 

亚洲必赢手机 39

亚洲必赢手机 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); 
            }
        }

亚洲必赢手机 41

亚洲必赢手机 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只优先等级:Above诺玛(Norma)l、BelowNormal、Highest、Lowest、Normal。公共语言运行库默认是Normal类型的。见下图:

亚洲必赢手机 43

亚洲必赢手机 44

直上代码来拘禁效率:

直接上代码来拘禁效率:

亚洲必赢手机 45

亚洲必赢手机 46

亚洲必赢手机 47

亚洲必赢手机 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); 
            }
        }

亚洲必赢手机 49

亚洲必赢手机 50

尽结果:

行结果:

亚洲必赢手机 51

亚洲必赢手机 52

方的代码中出两个线程,threadA,threadB和主线程,threadA优先级最高,threadB优先级最低。这同样碰由运行结果际遇呢足以看到,线程B
偶尔会合世在主线程和线程A前面。当有差不六个线程同时处于可尽状态,系统优先执行优先级较高之线程,但霎时才象征优先级较高之线程占有更多之CPU时间,并无意味一定假诺先行实施了优先级较高的线程,才汇合执行优先级较逊色之线程。

面的代码中爆发三单线程,threadA,threadB和主线程,threadA优先级最高,threadB优先级最低。这等同碰起运行结果被为可看来,线程B
偶尔会起于主线程和线程A后边。当起多单线程同时处于可尽状态,系统优先履优先级较高的线程,但迅即仅仅象征优先级较高之线程占有更多的CPU时间,并无表示早晚要先行实施完毕优先级较高的线程,才会尽优先级较逊色的线程。

先期级更强意味着CPU分配为该线程的工夫片越多,执行时间即多

预先级更强意味着CPU分配给该线程的命宫片越多,执行时固然多

优先级更小表示CPU分配为该线程的时片越少,执行时就少

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

   3、线程同步

   3、线程同步

  什么是线程安全:

  什么是线程安全:

  线程安全是负以当一个线程访问该类的某部数经常,举行保障,其他线程不可知开展走访直到该线程读取完,其他线程才可是下。不会师油但是生数未均等或者数传。

  线程安全是依在当一个线程访问该类的某数平时,举行维护,其他线程不可知展开走访直到该线程读取了,其他线程才然而使用。不会见出现数量未雷同或数额传。

   线程有或和其他线程共享有资源,比如,内存,文件,数据库等。当多独线程同时读写及同客共享资源的时节,可能会晤惹争持。这时候,大家需要引入线程“同步”机制,即诸君线程之间一旦发生只先行来后及,不克一如既往窝蜂挤上去抢作一团。线程同步的实在意思和字面意思恰好相反。线程同步的实事求是意思,其实是“排队”:多少个线程之间一旦排队,一个一个针对共享资源举办操作,而非是又开展操作。

   线程有或同其他线程共享有资源,比如,内存,文件,数据库等。当多少个线程同时读写及同客共享资源的时刻,可能会师惹争辩。那时候,咱们要引入线程“同步”机制,即诸君线程之间倘诺生个优先来晚到,不克同卷蜂挤上去抢作一团。线程同步的实在意思和字面意思恰好相反。线程同步的真正意思,其实是“排队”:几单线程之间一旦排队,一个一个对准共享资源举行操作,而无是以展开操作。

怎而兑现同啊,上边的例证大家将知名的单例模式以来吧。看代码

为啥要实现共同啊,下面的例子大家将出名的单例情势吧吧。看代码

亚洲必赢手机 53

亚洲必赢手机 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;
        }
    }

亚洲必赢手机 55

亚洲必赢手机 56

     
 单例情势就是是保险在全方位应用程序的生命周期中,在任几时刻,被指定的类似才发一个实例,并为客户程序提供一个抱该实例的大局访问点。但方代码来一个精通的题材,那就是是要多个线程同时失去抱这目的实例,那。。。。。。。。

     
 单例情势就是是管在尽应用程序的生命周期中,在任什么时候刻,被指定的类似才生一个实例,并为客户程序提供一个取该实例的大局访问点。但方代码有一个家喻户晓的题材,那尽管是一旦两单线程同时失去取这目标实例,那。。。。。。。。

咱俩队代码进行改动:

咱班代码实行改动:

亚洲必赢手机 57

亚洲必赢手机 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;
       }
}

亚洲必赢手机 59

亚洲必赢手机 60

透过改动后的代码。加了一个
lock(obj)代码块。这样就会实现协同了,倘若不是老了然的口舌,我们看前边继续教师~

经过改后底代码。加了一个
lock(obj)代码块。这样就能落实协同了,假诺不是蛮亮的口舌,我们看后继续上课~

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

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

  率先成立三只线程,两独线程执行与一个艺术,参考上边的代码:

  率先创制两只线程,两独线程执行及一个主意,参考下边的代码:

亚洲必赢手机 61

亚洲必赢手机 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);
            }
        }

亚洲必赢手机 63

亚洲必赢手机 64

尽结果:

行结果:

亚洲必赢手机 65

亚洲必赢手机 66

 

 

经者的执行结果,能够很是了然的观,两独线程是以以实施ThreadMethod这个办法,那眼看不切合大家线程同步的渴求。我们对代码举办修改如下:

经过者的履行结果,可以非凡了解的来看,四个线程是在以履行ThreadMethod这多少个办法,这明确不切合我们线程同步的渴求。大家对代码举行改动如下:

亚洲必赢手机 67

亚洲必赢手机 68

亚洲必赢手机 69

亚洲必赢手机 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);
                }
            } 
        }

亚洲必赢手机 71

亚洲必赢手机 72

尽结果:

行结果:

亚洲必赢手机 73

亚洲必赢手机 74

咱俩透过补加了 lock(this)
{…}代码,查看执行结果实现了咱回忆要之线程同步要求。不过大家明白this表示即好像实例的本身,那么来这样一种植情形,我们将要看的法子所在的色举办简单独实例A和B,线程A看实例A的点子ThreadMethod,线程B访问实例B的主意ThreadMethod,这样的话还可以达到线程同步的急需呢。

咱由此加加了 lock(this)
{…}代码,查看执行结果实现了咱回忆使的线程同步要求。可是咱领略this表示近期相近实例的自我,那么有这么一栽情形,我们将用看的点子所在的类举办有限个实例A和B,线程A看实例A的法门ThreadMethod,线程B访问实例B的法门ThreadMethod,这样的话仍是可以够达成线程同步的需为。

亚洲必赢手机 75

亚洲必赢手机 76

亚洲必赢手机 77

亚洲必赢手机 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);
                }
            }
        }

亚洲必赢手机 79

亚洲必赢手机 80

施行结果:

实施结果:

亚洲必赢手机 81

亚洲必赢手机 82

俺们汇合发现,线程又尚未落实共同了!lock(this)对于这种意况是雅的!所以待大家对代码进行改动!修改后的代码如下: 

我们会合发觉,线程又没实现协同了!lock(this)对于这种境况是特另外!所以用我们针对代码举办改动!修改后的代码如下: 

亚洲必赢手机 83

亚洲必赢手机 84

亚洲必赢手机 85

亚洲必赢手机 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);
                }
            }
        }

亚洲必赢手机 87

亚洲必赢手机 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)的用法很简短,看代码 

亚洲必赢手机 89

亚洲必赢手机 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);  //释放对象
            } 
        } 

亚洲必赢手机 91

亚洲必赢手机 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),。 

亚洲必赢手机 93

亚洲必赢手机 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);
            } 
        } 

亚洲必赢手机 95

亚洲必赢手机 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的表明。不知道看代码:

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

 首先大家定义一个攻击类,

亚洲必赢手机 97

亚洲必赢手机 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);
        }
    }

亚洲必赢手机 99

亚洲必赢手机 100

接下来于概念一个攻击类

下一场在概念一个攻击类

亚洲必赢手机 101

亚洲必赢手机 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);
        }
    }

亚洲必赢手机 103

亚洲必赢手机 104

实施代码:

实践代码:

亚洲必赢手机 105

亚洲必赢手机 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();
        }

亚洲必赢手机 107

亚洲必赢手机 108

出口结果:

输出结果:

亚洲必赢手机 109

亚洲必赢手机 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 一次。

  使用实例:

  使用实例:

亚洲必赢手机 111

亚洲必赢手机 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();  //释放锁
        }

亚洲必赢手机 113

亚洲必赢手机 114

 2、线程池

 2、线程池

   
  上边介绍了介绍了平常用的大部底多线程的例证,但每当其实支付被使用的线程往往是大气之同越来越复杂的,这时,每一遍都创线程、启动线程。从性能上来讲,这样做并无优异(因为各级动一个线程就要创立一个,需要占用系统开发);从操作及来讲,每一回都设开动,相比艰难。为是引入的线程池的概念。

   
  下边介绍了介绍了平日应用的大多数底多线程的例证,但以其实开发被使的线程往往是大量之同进一步复杂的,这时,每一趟都创线程、启动线程。从性能上来讲,这样做并无完美(因为各动一个线程就要创立一个,需要占用系统开发);从操作及来讲,每趟都如开动,相比较麻烦。为之引入的线程池的概念。

  好处:

  好处:

  1.减弱在创制同销毁线程上所花的时日跟系统资源的开销 
 
2.要非使用线程池,有或引致系统创设大气线程而招致消耗了系统内存和”过度切换”。

  1.减小在制造与销毁线程上所消费之日与系统资源的开销 
 
2.比方无使用线程池,有或造成系统成立大气线程而招致消耗了系统内存和”过度切换”。

以什么动静下使用线程池? 

在什么情状下使用线程池? 

    1.么任务处理的大运较短 
    2.欲处理的天职之多寡大 

    1.单个任务处理的辰相比较短 
    2.亟需处理的职责的数目大 

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

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

通过线程池创制的线程默认为后台线程,优先级默认为诺玛l。

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

代码示例:

代码示例:

亚洲必赢手机 115

亚洲必赢手机 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);
                } 
            } 
        }

亚洲必赢手机 117

亚洲必赢手机 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

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图