深入浅出多线程系列之五:一些同步构造(下篇)

简介:

1:CountdownEvent

Framework 4.0提供了一个CountdownEvent类,主要是让你等待多个线程。考虑下这样的场景:

有一个任务,3个人去做,你需要等这3个人都做完了才继续下一步操作。

下面就是:

复制代码
class  Thread15
    {
        
static  CountdownEvent _countdown  =   new  CountdownEvent( 3 );

        
public   static   void  MainThread()
        {
            
new  Thread(SaySomething).Start( " I'm thread 1 " );
            
new  Thread(SaySomething).Start( " I'm thread 2 " );
            
new  Thread(SaySomething).Start( " I'm thread 3 " );

            _countdown.Wait(); 
// 阻塞,直到Signal被调用三次
            Console.WriteLine( " All threads have finished speaking! " );
        }

        
static   void  SaySomething( object  thing)
        {
            Thread.Sleep(
1000 );
            Console.WriteLine(thing);
            _countdown.Signal();
        }
    }
复制代码

注意在构造函数中我们传递了3.代表我们要等待3个线程都结束。

 

2:ThreadPool.RegisterWaitForSingleObject

如果你的应用程序中有大量的线程都在一个WaitHandle上花费了大量的时间的时候,

你可以通过线程池的ThreadPool.RegisterWaitForSingleObject方法来提高资源的利用率,这个方法接受一个委托,当这个WaitHandle调用signal方法后,

方法的委托就会被执行了。 

复制代码
class  Thread16
    {
        
static  ManualResetEvent _starter  =   new  ManualResetEvent( false );

        
public   static   void  MainThread()
        {
            RegisteredWaitHandle reg 
=  ThreadPool.RegisterWaitForSingleObject
                (_starter, Go, 
" Some Data " - 1 true ); 
      // 在_starter上等待执行Go方法,-1,代表永远不超时,true代表只执行一遍,”Some Data”是传递的参数

            Thread.Sleep(
5000 );
            Console.WriteLine(
" Signaling worker... " );
            _starter.Set();     
// 唤醒等待的线程
            Console.ReadLine();
            reg.Unregister(_starter);  
// 取消注册。
        }

        
static   void  Go( object  data,  bool  timeOut)
        {
            Console.Write(
" Started -  "   +  data);
            Console.WriteLine(
" ThreadId: "   +  Thread.CurrentThread.ManagedThreadId);
        }

    }
复制代码

 

3:同步上下文:

通过继承ContextBoundObject类,并且加上Synchronization特性,CLR会自动的为你的操作加锁。

复制代码
// 继承自ContextBoundObject,且加上Synchronization特性修饰
    [Synchronization]
    
public   class  AutoLock:ContextBoundObject
    {
        
public   void  Demo()
        {
            Console.WriteLine(
" Start... " );
            Thread.Sleep(
1000 );
            Console.WriteLine(
" end " );
        }
    }
// 主线程:
    public   static   void  MainThread()
        {
            AutoLock safeInstance 
=   new  AutoLock();
            
new  Thread(safeInstance.Demo).Start();
            
new  Thread(safeInstance.Demo).Start();
            safeInstance.Demo();
        }
复制代码

输出为:

Start…

End

Start…

End

Start…

End

 

CLR会确保一次只有一个线程可以执行safeInstance里面的代码,它会自动的创建一个同步对象,然后

在每次调用方法或属性的时候都 lock它,从这个角度来讲safeInstance是一个同步上下文。

但是它是怎么样工作的,在Synchronization特性和System.Runtime.Remoting.Contexts命名空间中存在着线索。

一个ContextBoundObject被认为是一个远程(“remote”)对象.意味所有的方法调用都可以被介入。当我们实例化AutoLock的时候,CLR实际上返回了一个proxy对象,一个和AutoLock对象有着同样方法,同样属性的Proxy对象,在这里它扮演者中介的对象。这样就为自动加锁提供了介入的机会,在每一次方法调用上都会花费几微妙的时间来介入。

 

你可能会认为下面的代码会和上面的一样,是一样的输出结果:

复制代码
// 继承自ContextBoundObject,且加上Synchronization特性修饰
    [Synchronization]
    
public   class  AutoLock:ContextBoundObject
    {
        
public   void  Demo()
        {
            Console.WriteLine(
" Start... " );
            Thread.Sleep(
1000 );
            Console.WriteLine(
" end " );
        }

        
public   void  Test()
        {
            
new  Thread(Demo).Start();
            
new  Thread(Demo).Start();
            
new  Thread(Demo).Start();
            Console.ReadLine();
        }

        
public   static   void  RunTest()
        {
            
new  AutoLock().Test();
        }
    }

public   static   void  MainThread()
        {
            
// AutoLock safeInstance = new AutoLock();
            
// new Thread(safeInstance.Demo).Start();
            
// new Thread(safeInstance.Demo).Start();
            
// safeInstance.Demo();

            AutoLock.RunTest();
        }
复制代码

实际上这里我们会运行到Console.ReadLine方法这里,然后等待输入。

为什么??

因为CLR会确保一次只有一个线程能够执行AutoLock的代码,所以当主线程执行到Console.ReadLine方法的时候,

就开始等待输入了。如果你按下Enter,代码就和上面的输出一样了。

 

注:还有一些同步构造将在以后讲到.

 






本文转自LoveJenny博客园博客,原文链接:http://www.cnblogs.com/LoveJenny/archive/2011/05/24/2053682.html,如需转载请自行联系原作者
目录
相关文章
|
3天前
|
Java 云计算
Java多线程编程中的同步与互斥机制探析
在当今软件开发领域,多线程编程是一项至关重要的技能。本文将深入探讨Java中的同步与互斥机制,分析其在多线程环境下的应用及实现原理,帮助读者更好地理解并运用这一关键技术。
27 4
|
3天前
|
Python
在Python中,如何保证多个线程之间的同步?
在Python中,如何保证多个线程之间的同步?
26 4
|
3天前
|
Python
如何在Python中实现线程之间的同步和通信?
【2月更文挑战第17天】【2月更文挑战第51篇】如何在Python中实现线程之间的同步和通信?
|
3天前
|
算法 调度 索引
什么是多任务和线程?用线程写的一个udp同步聊天器
什么是多任务和线程?用线程写的一个udp同步聊天器
31 0
|
1天前
|
关系型数据库 MySQL Java
实时计算 Flink版产品使用合集之mysql通过flink cdc同步数据,有没有办法所有表共用一个dump线程
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
7 0
|
3天前
|
安全 C++
C++多线程编程:并发与同步
C++多线程编程:并发与同步
10 0
|
3天前
|
监控 安全 Java
一文讲明白Java中线程与进程、并发与并行、同步与异步
一文讲明白Java中线程与进程、并发与并行、同步与异步
8 1
|
3天前
|
安全 算法 Java
Java中的多线程并发控制与同步机制
【4月更文挑战第17天】 在现代软件开发中,Java作为一种广泛使用的编程语言,其对多线程的支持是构建高性能应用程序的关键。本文将深入探讨Java中的多线程并发控制与同步机制,包括基本的线程创建、生命周期管理,以及高级的并发工具如synchronized关键字、ReentrantLock类、并发集合和原子变量等。通过理论分析与实例演示,旨在为读者提供一个清晰的多线程并发控制与同步的实现框架,并指出在实践中如何避免常见的并发问题,如死锁、竞态条件和资源争用等。
|
3天前
|
安全 Java 开发者
Java中的多线程并发控制与同步机制
【4月更文挑战第17天】在Java编程中,多线程是实现并行处理和提高程序性能的重要手段。然而,随之而来的线程安全问题和数据一致性问题不容忽视。本文深入剖析了Java中多线程的并发控制与同步机制,包括synchronized关键字、显式锁Lock以及并发集合等高级特性。通过对比分析这些机制的原理和使用场景,旨在帮助开发者理解并合理运用于实际项目中,以解决并发环境下的数据竞争和资源冲突问题。