zoukankan      html  css  js  c++  java
  • 第16章 多线程

    16.1 线程的概念

    16.2 线程的基本操作

    16.2.1 创建新线程

    Thread th = new Thread()

    线程有以下几个常用的属性:

    ManagedThreadId属性,托管线程ID,在进程内唯一

    name属性,默认为空

    ThreadState属性,是一个位标记,描述了线程的当前运行状态:Background、Unstarted、Running、WaitSleepJoin、Stopped。

    16.2.2 查看当前线程

    Thread.CurrentThread.Name

    16.2.3 Sleep()方法

    public static void Sleep(int millisecondsTimeout);

    public static void Sleep(TimeSpan timeout);

    16.2.4 Interrupt()方法

    16.2.5 前台线程和后台线程

    前台后台区别:所有前台线程执行完毕后,应用程序进程结束,而无论后台进程是否结束。

    容易混淆的一个地方:后台线程的background标记就相当于前台线程的running标记,而不是background,running标记

    在创建一个线程之后,就应该对它的生存周期有完全的掌控,因此,不去管理后台线程,让它随主线程的结束而终结是很欠妥的做法,尤其是当后台线程还持有一些资源需要关闭时。当后台线程以这种方式退出时,即使位于finally块中的语句也不会执行。

    16.2.6 Join()方法

    等待线程执行结束后,在继续执行后面的代码

    16.2.7 Suspend()和Resume()方法

    用于挂起和继续执行已挂起的线程(不推荐使用)

    16.2.8 线程异常

    当工作线程抛出异常时,整个进程都会关闭,而不是仅结束抛出异常的线程(调用abort方法抛出ThreadAbortException异常除外)

    16.2.9 Abort()方法

    如果想要强制退出一个线程,可以调用Abort()方法,调用Abort()方法会抛出一个System.Threading.ThreadAbortException异常,该异常很特殊,因为即使不捕获它,也不会影响到整个进程。

    16.3 线程同步

    线程同步就是协调多个线程间的并发操作,以获得预期的确定的执行结果,消除多线程应用程序执行中的不确定性,包含两方面:

    1、保护资源,确保资源同时只能有一个(或指定个数)的线程访问,一般措施是获取锁和释放锁(锁机制)

    2、协调线程对资源的访问顺序,即确定某一资源只能现有线程A访问,再由线程B访问,一般措施是采用信号量机制。当B线程访问资源时,必须等待线程A先访问,线程A访问完后,发出信号量,通知线程B可以访问

    16.3.1 使用Monitor

    1.使用对象本身作为锁对象

    Monitor只能对引用类型加锁,否则会抛错

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource res = new Resource();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                th.Start();
                p.ThreadEntity();
                Console.Read();
            }
    
            void ThreadEntity()
            {
                Monitor.Enter(res);
                res.Record();
                Monitor.Exit(res);
            }
        }
    
        public class Resource
        {
            public string call;
            public void Record()
            {
                call += string.Format("{0}:{1}", Thread.CurrentThread.Name, DateTime.Now.Millisecond);
                Console.WriteLine(call);
            }
        }
    }
    View Code

    2.使用System.Object作为锁对象

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource res = new Resource();
            private object lockObject = new object();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                th.Start();
                p.ThreadEntity();
                Console.Read();
            }
    
            void ThreadEntity()
            {
                Monitor.Enter(lockObject);
                res.Record();
                Monitor.Exit(lockObject);
            }
        }
    
        public struct Resource
        {
            public string call;
            public void Record()
            {
                call += string.Format("{0}:{1}", Thread.CurrentThread.Name, DateTime.Now.Millisecond);
                Console.WriteLine(call);
            }
        }
    }
    View Code

    3.使用System.Type作为锁对象

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            private object lockObject = new object();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                th.Start();
                p.ThreadEntity();
                Console.Read();
            }
    
            void ThreadEntity()
            {
                Monitor.Enter(typeof(Resource));
                Resource.Record();
                Monitor.Exit(typeof(Resource));
            }
        }
    
        public static class Resource
        {
            public static string call;
            public static void Record()
            {
                call += string.Format("{0}:{1}", Thread.CurrentThread.Name, DateTime.Now.Millisecond);
                Console.WriteLine(call);
            }
        }
    }
    View Code

    4.使用lock语句

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource res = new Resource();
            private object lockObject = new object();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                //th.IsBackground = true;
                th.Start();
                p.ThreadEntity();
                Console.Read();
            }
    
            void ThreadEntity()
            {
                lock (res)
                {
                    try
                    {
                        Resource.Record();
                    }
                    catch(Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }
    
        public class Resource
        {
            public static string call;
            public static void Record()
            {
                call += string.Format("{0}:{1}", Thread.CurrentThread.Name, DateTime.Now.Millisecond);
                Console.WriteLine(call);
                throw new Exception();
            }
        }
    }
    View Code

    5.创建线程安全类型

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    using System.Runtime.CompilerServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource res = new Resource();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                //th.IsBackground = true;
                th.Start();
                p.ThreadEntity();
                Console.Read();
            }
    
            void ThreadEntity()
            {
                res.Record();
            }
        }
    
        public class Resource
        {
            public string call;
            [MethodImpl(MethodImplOptions.Synchronized)]
            public void Record()
            {
                call += string.Format("{0}:{1}", Thread.CurrentThread.Name, DateTime.Now.Millisecond);
                Console.WriteLine(call);
            }
        }
    }
    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    using System.Runtime.CompilerServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static Resource res = new Resource();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                //th.IsBackground = true;
                th.Start();
                p.ThreadEntity();
                //Console.WriteLine(res.Index);
                Console.Read();
            }
    
            void ThreadEntity()
            {
                lock (res)
                {
                    for (int i = 0; i <= 2; i++)
                    {
                        lock (res)
                        {
                            res.Index = res.Index + 1;
                            Console.WriteLine("{0}:{1}", Thread.CurrentThread.Name, res.Index);
                        }
                    }
                }
            }
        }
    
        public class Resource
        {
            private int _index;
            public int Index
            {
                get
                {
                    lock (this)
                    {
                        return _index;
                    }
                }
                set
                {
                    lock (this)
                    {
                        _index = value;
                    }
                }
            }
        }
    }
    View Code

    锁的粒度对于程序执行的顺序和结果是很重要的。

    6.使用Monitor协调线程执行顺序

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    using System.Runtime.CompilerServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource res = new Resource();
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.ThreadEntity);
                th.Name = "Worker";
                //th.IsBackground = true;
                th.Start();
                //Thread.Sleep(1000);
                lock (p.res)
                {
                    if (string.IsNullOrEmpty(p.res.data))
                    {
                        bool isTimeout = Monitor.Wait(p.res, 100);
                        Console.WriteLine(isTimeout);
                    }
                    Console.WriteLine("data={0}", p.res.data);
                }
                //Console.WriteLine(res.Index);
                Console.Read();
            }
    
            void ThreadEntity()
            {
                lock (res)
                {
                    res.data = "Retrived";
                    Monitor.Pulse(res);
                }
            }
        }
    
        public class Resource
        {
            public string data;
        }
    }
    View Code

     7.死锁

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    using System.Runtime.CompilerServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource mainRes = new Resource() { data = "Main" };
            Resource workerRes = new Resource() { data = "Worker" };
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.T2);
                th.Name = "Worker";
                //th.IsBackground = true;
                th.Start();
                T1(p);
                Console.Read();
            }
    
            static void T1(Program p)
            {
                lock (p.mainRes)
                {
                    Thread.Sleep(10);
                    lock (p.workerRes)
                    {
                        Console.WriteLine(p.workerRes.data);
                    }
                }
            }
    
            void T2()
            {
                lock (workerRes)
                {
                    Thread.Sleep(10);
                    lock (mainRes)
                    {
                        Console.WriteLine(mainRes.data);
                    }
                }
            }
        }
    
        public class Resource
        {
            public string data;
        }
    }
    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    using System.IO;
    using System.Threading;
    using System.Runtime.CompilerServices;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            Resource mainRes = new Resource() { data = "Main" };
            Resource workerRes = new Resource() { data = "Worker" };
            static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "Main";
                Program p = new Program();
                Thread th = new Thread(p.T2);
                th.Name = "Worker";
                //th.IsBackground = true;
                th.Start();
                T1(p);
                Console.Read();
            }
    
            static void T1(Program p)
            {
                lock (p.mainRes)
                {
                    Thread.Sleep(10);
                    int i = 0;
                    while (i < 3)
                    {
                        if (Monitor.TryEnter(p.workerRes))
                        {
                            Console.WriteLine(p.workerRes.data);
                            Monitor.Exit(p.workerRes);
                            break;
                        }
                        else
                        {
                            i++;
                            Thread.Sleep(1000);
                        }
                    }
                    if (i == 3)
                    {
                        Console.WriteLine("{0}:deadlock", Thread.CurrentThread.Name);
                    }
                }
            }
    
            void T2()
            {
                lock (workerRes)
                {
                    Thread.Sleep(10);
                    int i = 0;
                    while (i < 3)
                    {
                        if (Monitor.TryEnter(mainRes))
                        {
                            Console.WriteLine(workerRes.data);
                            Monitor.Exit(mainRes);
                            break;
                        }
                        else
                        {
                            i++;
                            Thread.Sleep(1000);
                        }
                    }
                    if (i == 3)
                    {
                        Console.WriteLine("{0}:deadlock", Thread.CurrentThread.Name);
                    }
                }
            }
        }
    
        public class Resource
        {
            public string data;
        }
    }
    View Code
  • 相关阅读:
    几种委托的解释
    Python中的编码风格
    Python的循环
    Python中操作文件
    Python的random模块、string模块、time模块、os模块
    Python中的函数
    Python的数据类型
    使用iview Form 的resetFields()在f12下报错
    滚动条的滚动距离
    编程学习之资源
  • 原文地址:https://www.cnblogs.com/liuslayer/p/5405257.html
Copyright © 2011-2022 走看看