CLR via C#:基元线程同步构造

基础知识:如下所示:
1.线程安全指的是多个线程试图同时访问数据时,数据不会被破坏。
2.FCL保证所有的静态函数都是线程安全的,但是不保证所有的实例函数都是线程安全的。
3.建议自定义类库的所有静态函数以及协调线程的实例函数都是线程安全的,其他实例函数都是非线程安全的。
4.将线程从用户模式和内核模式之间相互切换时会造成巨大的性能损失。
5.C#编译器,JIT编译器以及CPU会在代码的原始意图被保留的情况下,尽可能的优化掉不用的代码。这种优化后的代码在单线程中表现会正常,但是在多线程中就可能会造成意图不一致。
6.Thread.Sleep(timeout)函数具有以下特性:
1>.当timeout = -1时,调用该函数的线程永远不会再被系统进行调度。但这样做没实际意义,更好的做法是退出调用该函数的线程,回收它的栈和内核对象。
2>.当timeout = 0时,如果没有相同或者更高优先级的其他可调度线程,那么调用该函数的线程就会被系统重新调度;否则系统就会调度其他可调度线程。
3>.当timeout > 0时,系统会使调用该函数的线程在大致指定的时间里不被调度。
7.Thread.Yield()函数具有以下特性:
1>.如果没有其他可调度线程准备在当前CPU上运行,该函数就返回false且调用该函数的线程会继续运行。
2>.如果有其他可调度线程准备在当前CPU上运行,该函数就返回true且调用该函数的线程会被系统挂起;然后所选的其他可调度线程运行一个时间片后,调用该函数的线程会被系统再次调度。
8.Thread.SpinWait函数用来告知系统将调用该函数的线程挂起,从而使CPU有机会切换到另一个线程并允许它运行。

用户模式构造:具有以下特性:
1.用户模式构造使用特殊CPU指令来协调线程。
2.在用户模式构造上阻塞的线程池线程永远不认为已阻塞,所以线程池不会创建新线程来替换这种临时阻塞的线程。
3.线程一直在一个CPU上运行时,就会造成活锁。
4.异变构造指的是在特定的时间,对一个简单数据类型的变量进行原子性的读或写操作。具有以下特性:
1>.Volatile.Wrire(location, value)函数强迫location中的值在调用时写入。此外,按照编码顺序,之前的加载和存储操作必须在调用Volatile.Wrire(location, value)函数之前发生。
2>.Volatile.Read(location)函数强迫location中的值在调用时读取。此外,按照编码顺序,之后的加载和存储操作必须在调用Volatile.Read(location)函数之后发生。
3>.当线程通过共享内存相互通信时,调用Volatile.Write函数来写入最后一个值,调用Volatile.Read函数来读取第一个值。
4>.volatile关键字用来修饰类型的静态或者实例字段。该字段的类型可以为Boolean,(S)Byte,(U)Int16,(U)Int32,(U)IntPtr,Single,class引用类型以及enum。
5>.volatile关键字告知C#编译器以及JIT编译器不要将异变字段缓存到CPU的寄存器中,确保异变字段的所有读写操作都是在RAM中进行。
6>.volatile关键字告知JIT编译器确保对异变字段的所有访问都是以调用Volatile.Read或者Volatile.Wrire函数的方式进行。
7>.C#不支持以传递引用的方式将volatile关键字修饰的字段传递给函数。
5.互锁构造指的是在特定的时间,对一个简单数据类型的变量进行原子性的读和写操作。具有以下特性:
1>.调用Interlocked类型的函数时,该函数之前发生的任何变量写入操作都在调用该函数之前发生,该函数之后发生的任何变量读取操作都在调用该函数之后发生。
2>.Interlocked.Increment(location)函数用来执行"return (++location);"操作。
3>.Interlocked.Decrement(location)函数用来执行"return (–location);"操作。
4>.Interlocked.Add(location, value)函数用来执行"return (location += value);"操作。
5>.Interlocked.Exchange(location, value)函数用来执行"old = location; location = value; return old;"操作。
6>.Interlocked.CompareExchange(location, value, comparand)函数用来执行"old = location; if (location == comparand) location = value; return old; “操作。
6.自旋锁指的是让一个线程暂时"原地打转”,以免它跑去跟另一个线程竞争资源。具有以下特性:
1>.自旋锁会浪费宝贵的CPU时间,所以一般用它来保护执行速度非常快的代码区域。
2>.自旋锁不要用在单CPU上,因为在这种机器上,一方面是希望获得锁的线程自旋,一方面是占有锁的线程不能快速释放锁,从而有可能造成活锁发生。
3>.SpinLock实例不能作为参数传递给函数,因为该实例会被复制,从而造成失去所有的同步。
4>.SpinLock实例不能作为readonly的类型字段,因为在操作锁的时候,该实例内部状态必须改变。

内核模式构造:具有以下特性:
1.线程通过内核模式构造获取其他线程拥有的资源时,Windows会阻塞线程以避免它浪费CPU时间。当资源变的可用时,Windows会恢复线程,允许它访问资源。
2.线程一直阻塞时,就会造成死锁。
3.由于内核模式构造需要Windows操作系统的配合,还需要在托管堆代码,本机用户模式代码以及本机内核模式代码之间来回的转换,从而造成内核模式构造比用户模式构造慢的多。
4.内核模式构造可以实现本机和托管线程相互之间的同步。
5.内核模式构造可同步在同一台机器的不同进程中运行的线程。
6.内核模式构造可应用于安全性设置,防止未经授权的账户访问它们。
7.线程可以一直阻塞,直到集合中所有的或者任意的内核模式构造可用。
8.在内核模式构造上阻塞的线程可以指定的超时值。指的时间内访问不到希望的资源,线程就可以解除阻塞并执行其他任务。
9.WaitHandle抽象基类封装了内核模式构造的公共行为。具有以下特性:
1>.内部包含一个SafeWaitHandle类型私有字段。该私有字段主要是用来存储WaitHandle派生类型构造对象时分配的Win32内核对象句柄。
2>.WaitOne函数:如果指定的底层内核对象收到信号就返回true;超时就返回false。该函数在内部会调用Win32的WaitForSingleObjectEx函数。
3>.WaitAll函数:如果指定的底层内核对象集合中的所有对象都收到信号就返回true;超时就返回false。该函数在内部会调用Win32的WaitForMultipleObjecstEx(true)函数。
4>.WaitAny函数:如果指定的底层内核对象集合中的任一对象收到信号就返回该对象在集合中的索引值;超时就返回WaitHandle.WaitTimeout。该函数在内部会调用Win32的WaitForMultipleObjecstEx(false)函数。
5>.WaitAll和WaitAny函数中指定的底层内核对象集合的长度不能超过64,否则就会抛出NotSupportedException。
6>.Dispose函数:该函数内部会调用Win32的CloseHandle函数,从而关闭底层内核对象的句柄。由于开发者不知道是否有其他线程正在使用着该底层内核对象,所以建议不要显示调用Dispose函数,而是交给GC去智能执行。
10.事件构造具有以下特性:
1>.EventWaitHandle(事件构造类型)是从WaitHandle派生而来。
2>.AutoResetEvent(自动重置事件类型)和ManualResetEvent(手动重置事件类型)是从EventWaitHandle派生而来。
3>.EventWaitHandle构造函数内部会调用Win32的CreateEvent函数来创建指定事件重置模式和指定初始状态值的对象。
4>.EventWaitHandle.OpenExisting函数内部会调用Win32的OpenEvent函数。当指定名称的内核对象不存在,就抛出一个WaitHandleCannotBeOpenedException。当指定名称的内核对象存在,就将句柄值存储在一个新的EventWaitHandle对象中,然后返回该新的EventWaitHandle对象。
5>.EventWaitHandle.Set函数用来将对象的状态值设置成true并且返回true。
6>.EventWaitHandle.Reset函数用来将对象的状态值设置成false并且返回true。
7>.当AutoResetEvent对象的状态值为false时,系统会阻塞在该对象上等待的所有线程。当AutoResetEvent对象的状态值为true时,系统会唤醒在该对象上阻塞的一个线程,然后立即将状态值设置为false。
8>.当ManualResetEvent对象的状态值为false时,系统会阻塞在该对象上等待的所有线程。当ManualResetEvent对象的状态值为true时,系统会唤醒在该对象上阻塞的所有线程。
11.信号量构造具有以下特性:
1>.Semaphore(信号量构造类型)是从WaitHandle派生而来。
2>.Semaphore构造函数内部会调用Win32的CreateSemaphore函数来创建指定初始计数值和最大计数值的对象。
3>.Semaphore.OpenExisting函数内部会调用Win32的OpenSemaphore函数。当指定名称的内核对象不存在,就抛出一个WaitHandleCannotBeOpenedException。当指定名称的内核对象存在,就将句柄值存储在一个新的Semaphore对象中,然后返回该新的Semaphore对象。
4>.Semaphore.Release(releaseCount)函数会将对象的旧计数值加上releaseCount参数值来得到一个新计数值。当新计数值大于最大计数值时,就会抛出SemaphoreFullException;否则就返回旧计数值。
5>.当Semaphore对象的计数值等于0时,系统会阻塞在该对象上等待的所有线程。当Semaphore对象的计数值大于0时,系统会唤醒在该对象上阻塞的最多计数值个线程,每当唤醒一个线程,该对象的计数值就会减1。
12.互斥体构造具有以下特性:
1>.Mutex(互斥体构造类型)是从WaitHandle派生而来。
2>.Mutex构造函数内部会调用Win32的CreateMutex函数来创建指定线程标识和递归计数值的对象。
3>.Mutex.OpenExisting函数内部会调用Win32的OpenMutex函数。当指定名称的内核对象不存在,就抛出一个WaitHandleCannotBeOpenedException。当指定名称的内核对象存在,就将句柄值存储在一个新的Mutex对象中,然后返回该新的Mutex对象。
4>.调用Mutex.ReleaseMutex函数的线程标识跟Mutex对象的线程标识不一致时,就会抛出ApplicationException;否则就会将Mutex对象的递归计数值减1。当Mutex对象的递归计数值为0时,系统就会唤醒在Mutex对象上阻塞的一个线程,并且使用该线程来设置Mutex对象的线程标识和递归计数值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值