zoukankan      html  css  js  c++  java
  • 多线程中线程同步的几种方式

    原连接(msdn):   http://msdn.microsoft.com/zh-cn/library/ms173179(v=vs.90).aspx

    线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。

        对于整数数据类型的简单操作,可以用 Interlocked 类的成员来实现线程同步。对于其他所有数据类型和非线程安全的资源,只有使用本主题中的结构才能安全地执行多线程处理。

    lock 关键字


    lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。                

    lock 语句以关键字 lock 开头,它有一个作为参数的对象,在该参数的后面还有一个一次只能由一个线程执行的代码块。例如:                

    public class TestThreading
    {
        private System.Object lockThis = new System.Object();
    
        public void Function()
        {
    
            lock (lockThis)
            {
                // Access thread-sensitive resources.
            }
        }
    
    }
    
    
    

    提供给 lock 关键字的参数必须为基于引用类型的对象,该对象用来定义锁的范围。在上面的示例中,锁的范围限定为此函数,因为函数外不存在任何对对象 lockThis 的引用。如果确实存在此类引用,锁的范围将扩展到该对象。严格地说,提供给 lock 的对象只是用来唯一地标识由多个线程共享的资源,所以它可以是任意类实例。然而,实际上,此对象通常表示需要进行线程同步的资源。例如,如果一个容器对象将被多个线程使用,则可以将该容器传递给 lock,而 lock 后面的同步代码块将访问该容器。只要其他线程在访问该容器前先锁定该容器,则对该对象的访问将是安全同步的。

                        与 lock 关键字类似,监视器防止多个线程同时执行代码块。Enter 方法允许一个且仅一个线程继续执行后面的语句;其他所有线程都将被阻止,直到执行语句的线程调用 Exit。这与使用 lock 关键字一样。事实上,lock 关键字就是用 Monitor 类来实现的。例如:                

    lock (x)
    {
        DoSomething();
    }
    
    
    

    这等效于:                

     
    System.Object obj = (System.Object)x;
    System.Threading.Monitor.Enter(obj);
    try
    {
        DoSomething();
    }
    finally
    {
        System.Threading.Monitor.Exit(obj);
    }
    
    
    

    使用 lock 关键字通常比直接使用 Monitor 类更可取,一方面是因为 lock 更简洁,另一方面是因为 lock 确保了即使受保护的代码引发异常,也可以释放基础监视器。这是通过 finally 关键字来实现的,无论是否引发异常它都执行关联的代码块。

                  

                        使用锁或监视器对于防止同时执行区分线程的代码块很有用,但是这些构造不允许一个线程向另一个线程传达事件。这需要“同步事件”,它是有两个状态(终止和非终止)的对象,可以用来激活和挂起线程。让线程等待非终止的同步事件可以将线程挂起,将事件状态更改为终止可以将线程激活。如果线程试图等待已经终止的事件,则线程将继续执行,而不会延迟。                

                        同步事件有两种:AutoResetEventManualResetEvent。它们之间唯一的不同在于,无论何时,只要 AutoResetEvent 激活线程,它的状态将自动从终止变为非终止。相反,ManualResetEvent 允许它的终止状态激活任意多个线程,只有当它的 Reset 方法被调用时才还原到非终止状态。                

                        可以通过调用 WaitOneWaitAnyWaitAll 等中的某个等待方法使线程等待事件。WaitHandle.WaitOne() 使线程一直等待,直到单个事件变为终止状态;WaitHandle.WaitAny() 阻止线程,直到一个或多个指示的事件变为终止状态;WaitHandle.WaitAll() 阻止线程,直到所有指示的事件都变为终止状态。当调用事件的 Set 方法时,事件将变为终止状态。                

                        在下面的示例中,创建了一个线程,并由 Main 函数启动该线程。新线程使用 WaitOne 方法等待一个事件。在该事件被执行 Main 函数的主线程终止之前,该线程一直处于挂起状态。一旦该事件终止,辅助线程将返回。在本示例中,因为事件只用于一个线程的激活,所以使用 AutoResetEventManualResetEvent 类都可以。                

    using System;
    using System.Threading;
    
    class ThreadingExample
    {
        static AutoResetEvent autoEvent;
    
        static void DoWork()
        {
            Console.WriteLine("   worker thread started, now waiting on event...");
            autoEvent.WaitOne();
            Console.WriteLine("   worker thread reactivated, now exiting...");
        }
    
        static void Main()
        {
            autoEvent = new AutoResetEvent(false);
    
            Console.WriteLine("main thread starting worker thread...");
            Thread t = new Thread(DoWork);
            t.Start();
    
            Console.WriteLine("main thread sleeping for 1 second...");
            Thread.Sleep(1000);
    
            Console.WriteLine("main thread signaling worker thread...");
            autoEvent.Set();
    
    Console.WriteLine("main thread signaling worker thread...2");
            Thread.Sleep(10000); }
    }
  • 相关阅读:
    记账程序2.0
    安装redHat6.5详细图文教程
    redHat6设置ip地址
    如何开通B站的直播空间
    python实战技巧之两个字典,如何实现键同则值相加【不等长或等长】
    python实战技巧之去除列表中的空值元素
    python实战技巧之两个不等长列表让里面的数字一一对应地相加
    python实战技巧之两个列表实例中,如何让里面的数字一一对应地相加【对于两个列表是等长的情况】
    java基础_网络编程
    java基础_String
  • 原文地址:https://www.cnblogs.com/chengjunwei/p/3431605.html
Copyright © 2011-2022 走看看