线程同步

  • 1.基本的原子操作

    • 可借助Inerlocked类,无需锁定任何对象即可获取到正确结果,Inerlock提供了Increment、Decement和Add等基本数学操作的原子方法:Interlocked.Incement(ref _count)
  • 2.Mutex类同步两个单独的线程,Mutex是一种原始的同步方式,只对一个线程授予对共享资源的独占访问
    • 主程序启动时,var m = new MutexName(false,MutexName)定义指定名称的互斥量,innitialOwner标志为false
    • 具名的互斥量是全局的操作系统对象,务必正确关闭互斥量,最好使用using代码块包裹互斥对象
    • 可用于不同的程序中同步线程,可被推广到大量的使用场景中
  • 3.使用SemaphoreSlim类
    • static SemaphoreSlim _semaphore = new SemaphoreSlim(4);

      • 指定允许的并发线程数量
    • 当有一个线程完毕后,使用_semaphore.Release()发出信号完成工作
    • 混合模式:允许我们在等待时间很短的情况下无需使用上下文切换
  • 4.AutoResetEvent类
    • 借助此类可以从一个线程向另一个线程发送通知。内核时间模式,等待时间不能太长
    • AutoResetEvent在调用Set()把信号量释放后(信号量设置为True)然后自动返回终止状态(信号量为False)
  • 5.ManualResetEventSlim类
    • 混合模式
    • 在调用set后,需要手动调用ReSet()恢复到终止状态。
    • ManualResetSlim是AutoResetEvent的简化版本,是4.0新增的类,使用wait()方法阻止线程
  • 6.CountDownEvent
    • 如何使用CountdownEvent信号类来等待直到一定数量的操作完成
    • 定义最多能够进入关键代码的线程数:static CountdownEvent _countdown =new CountdownEvent(2);
    • 主要的两个方法:主线程中调用wait()等待、子线程中完毕后要调用Signal()发出信号表示事情做完,
    • 还可以动态的设计等待线程数量
  • 7.Barrier
    • 指定我们想要同步的两个线程,子线程在调用SinalAndWait方法后会执行一个回调函数,
  • 8.ReaderWriterLockSlim
    • 创建一个线程安全机制,在多线程中对一个集合进行读写操作,代表了一个管理资源访问的锁,允许多个线程同时读取,以及独占。
  • 9.SpinWait
    • 介绍不使用内核模式的方式来使线程等待,SpinWait是一个混合同步构造,被设计为使用用户模式等待一段时间然后切换到内核模式以节省CPU时间。
  • 简介
    • 当一个线程执行递增和递减操作时,其他线程需要依次等待,这就叫做线程同步
    • 多线程同时使用共享对象会产生竞争条件的问题
    • 同步线程使得对共享对象的操作能够以正确的顺序执行
  • 如何实现线程同步
    • 1.尽量避免使用共享对象,那么就无须进行线程同步,重新设计程序可以移除共享状态,从而去掉复杂的同步构造

      2.必须使用共享状态,就只使用原子操作:操作只占用一个量子的时间,一次就可以完成,所以只有当前操作完成之后,其他线程才能执行其他操作,因此无须实现其他线程等待当前操作完成,避免了使用锁,也排除了死锁

      3.内核模式:如果上述两种方法还是不行,那么就不得不使用不同的方式来协调线程,第一种方式:设置等待的线程为阻塞状态(:线程处于阻赛状态只会占用尽可能少的CPU时间,意味着将至少引入一次所谓的上下文切换(context switch)(:操作系统的线程调度器)),调度器会保存等待的线程状态,并切换到另一个线程,依次恢复等待的线程状态。这需要消耗相当多的资源。如果线程需要被挂起的很长的时间,这样做是值得的。这种方式简称为内核模式(kernel_mode),只有操作系统的内核才能阻止线程使用CPU时间。

      4.用户模式:如果线程只需要等待一小段时间,最好只是简单的等待,而不用将线程切换到阻塞状态,虽然线程切换到阻塞状态,虽然线程等待会浪费CPU时间,但我们节省了上下文切换耗费的CPU时间,模式为:用户模式(user_mode)。如果线程需要等待较长时间会浪费大量时间

      5.混合模式(hybrid):合理的使用内核模式和混合模式,尝试使用用户模式等待,如果线程等待了足够长的时间,则会切换到阻塞状态以节省CPU资源

时间: 2024-09-30 04:00:49

线程同步的相关文章

[.net]基元线程同步构造

1 /* 基元线程同步构造 2 用户模式构造: 3 易变构造(Volatile Construct) 4 互锁构造(Interlocked Construct):自旋锁(Spinlock) 乐观锁(Optimistic Concurrency Control,乐观并发控制) 5 内核模式构造: 6 事件构造(Event) 7 信号量构造(Semaphore) 8 互斥体构造(Mutex) 9 */ 10 11 //易变构造,Volatile.Write()之前的所有字段写入操作,必须再该方法调用

iOS多线程编程:线程同步总结 NSCondtion

1:原子操作 - OSAtomic系列函数 iOS平台下的原子操作函数都以OSAtomic开头,使用时需要包含头文件<libkern/OSBase.h>.不同线程如果通过原子操作函数对同一变量进行操作,可以保证一个线程的操作不会影响到其他线程内对此变量的操作,因为这些操作都是原子式的.因为原子操作只能对内置类型进行操作,所以原子操作能够同步的线程只能位于同一个进程的地址空间内. 2:锁 - NSLock系列对象 iOS平台下的锁对象为NSLock对象,进入锁通过调用lock函数,解锁调用unl

线程同步之EVENT

事件可传信给其他线程,表示某些条件现在已具备,比如有可用的消息. 事件可分为手动复位和自动复位,前者可传信给许多同时等待事件的线程而且可以被复位. 自动复位的事件传信给单个等待时间的线程,该事件会自动复位. Applications can use event objects in a number of situations to notify a waiting thread of the occurrence of an event. For example, overlapped I/O

【java并发】(2) Java线程同步:synchronized锁住的是代码还是对象

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在方法上. 关键是,不要认为给方法或者代码段加上synchronized就万事大吉,看下面一段代码: class Sync { public synchronized void test() { System.out.println("test开始.."); try { Thread.sle

Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会引起此共享资源的不一致性.因此,为避免线程安全问题,应该避免多线程环境下对此共享资源的并发访问. 线程安全问题多是由全局变量和静态变量引起的,当多个线程对共享数据只执行读操作,不执行写操作时,一般是线程安全的:当多个线程都执行写操作时,需要考虑线程同步来解决线程安全问题. 二.线程同步(synchr

系统API函数实现多线程及线程同步

1.线程的创建 须包含头文件:#include <windows.h> HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); lpThreadAttributes:指向SECURI

Java进击C#——语法之线程同步

上一章我们讲到关于C#线程方向的应用.但是笔者并没有讲到多线程中的另一个知识点--同步.多线程的应用开发都有可能发生脏数据.同步的功能或多或少都会用到.本章就要来讲一下关于线程同步的问题.根据笔者这几年来的.NET开发可以了解到的同步方式至少有四种以上.如.lock.volatile.Monitor等. lock方式 对lock的关键字作用跟JAVA的synchronized关键字类似.但有一定的差别.JAVA的synchronized关键字可能修饰在方法上面.可惜C#却不能修饰在方法上面.用法

经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

Linux系统开发9 线程同步

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统编程8 线程同步 多线程共享资源,不加锁,同步互斥演示 多线程共享资源,加锁,同步互斥演示 读写锁:3个写线程,5个读线程,不加锁,并行处理 读写锁:3个写线程,5个读线程,加读写锁,串行处理 条件变量:生产消费者模型 信号量 进程间锁 文件锁: 习题 死锁,哲学家就餐 多线程共享资源,不加锁,同步互斥演示 [email protected]:~/linux_c/thread$ ca

线程同步方式比较

用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区. 内核模式下的方法有:事件,信号量,互斥量. 临界区 保证在某一时刻只有一个线程能访问数据的简便办法.在任意时刻只允许一个线程对共享资源进行访问.如果有多个线程试图同时访问临界区,那么 在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开.临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操 作共享资源的目的. 仅能在同一进程内使用 互斥量 Mutex 互斥量跟临界区很相似,只有拥有互