C# 多线程之线程同步
多线程间应尽量避免同步问题,最好不要线程间共享数据。如果必须要共享数据,就需要使用同步技术,确保一次只有一个线程访问和改变共享状态。
一::lock语句
lock语句事设置锁定和接触锁定的一种简单方法。其语法非常简单:
lock (obj)
{
// 需要发生同步的代码区
}
将共享数据的操作代码,放在上述的“{...}”区域内。锁定的对象(obj)必须是引用类型,如果锁定一个值类型,实际是锁定了它的一个副本,并没有实现锁定功能。
一般地,被锁定对象需要被创建为 私有 只读 引用类型:
private readonly object obj = new object();
二::Interlocked类
Interlocked类用于使变量的简单语句原子化。它提供了以线程安全的方式递增、递减、交换和读取值的方法。
private int stateFlag = ;
public int IncrementState
{
//get
//{
// lock (this)
// {
// stateFlag++;
// return stateFlag;
// }
//}
get
{
return Interlocked.Increment(ref stateFlag); // using System.Threading;
//Interlocked.Decrement(ref V0);
//Interlocked.Exchange(ref V1, ref V2);
//Interlocked.Read(ref V0);
}
}
三::Monitor类
与lock相似,C#的lock语句被编译器解析为使用Monitor类。锁定开始相当于 Monitor.Enter(obj) 方法,该方法会一直等待,直到线程被对象锁定。解除锁定后线程进入同步阶段,使用 Monitor.Exit(obj)方法解除锁定,编译器将它与try块的finally结合。方法一中的代码,相当于:
Monitor.Enter(obj);
try
{
// 需要发生同步的代码区
}
finally
{
Monitor.Exit(obj);
}
与lock语句相比,Monitor类的优点在于:可以添加一个等待北锁定的超时值。这样就不会无限期等待被锁定,而可以使用 TryEnter() 方法,给一个超时参数。
bool lockTaken = false;
Monitor.TryEnter(obj, , ref lockTaken);
if (lockTaken)
{
try
{
// acquired the lock
// synchronized region for obj
}
finally
{
Monitor.Exit(obj);
}
}
else
{
// didn't get the lock,do something else
}
如果obj被锁定,TryEnter() 方法就会把 bool 型引用参数 lockTaken 设置为 true,并同步地访问由 obj 锁定的状态。如果另一线程 锁定 obj 的时间超过 500 毫秒,Try Enter() 方法就把变量 lockTaken 设为 false ,线程不再等待,而是用于执行其它操作。也许在之后,该线程会尝试再次被锁定。
四::SpinLock结构
它是一个结构体(struct),用法极类似于Monitor类。获得锁用 Enter()或TryEnter() 方法,释放锁用 Exit() 方法。它还提供了属性 IsHeld 和 IsHeldByCurrentThred ,指定当前是否被锁定。
SpinLock mSpinLock = new SpinLock(); // 最好只是用一个 SpinLock
public void fun1()
{
// .....
bool lockTaken = false;
mSpinLock.Enter(ref lockTaken);
try
{
// synchronized region
}
finally
{
mSpinLock.Exit();
}
// ...
}
public void fun2()
{
// .....
bool lockTaken = false;
mSpinLock.TryEnter(, ref lockTaken);
if (lockTaken)
{
try
{
// synchronized region
}
finally
{
mSpinLock.Exit();
}
}
else
{
// didn't get the lock,do something else
}
// ...
}
SpinLock结构体是 .Net 4 新增。它适用于:有大量的锁,且锁定时间都非常短。程序需要避免使用多个 SpinLock 结构,也不要调用任何可能阻塞的内容。
五::WaitHandle 基类
WaitHandle是一个抽象基类,用于等待一个信号的设置。可以等待不同的信号,因为WaitHandle是一个基类,可以从中派生一些类。
public delegate int TakesAWhileDelegate(int data, int ms); // 声明委托
public void Main()
{
TakesAWhileDelegate vTAwdl = TakesAWhile;
IAsyncResult vAr = vTAwdl.BeginInvoke(, , null, null);
while(true)
{
Console.Write(".");
if (vAr.AsyncWaitHandle.WaitOne(, false)) // 等待 vAr.AsyncWaitHandle 收到信号(超时300毫秒)
{
Console.WriteLine("Can get the result now.");
break;
}
}
int result = vTAwdl.EndInvoke(vAr);
Console.WriteLine("Result:{0}", result);
Console.Read();
} int TakesAWhile(int data, int ms)
{
Console.WriteLine("TakesAWhile started");
Thread.Sleep(ms);
Console.WriteLine("TakesAWhile completed");
return ++data;
}

以上实例代码,使用”异步委托", BeginInvoke() 方法返回一个实现了 IAsycResult接口的对象。使用 IAsycResult 接口,可以用AsycResult属性访问 WaitHandle 基类。在调用WaitOne()方法时,线程等待一个与等待句柄相关的信号。
使用 WaitHandle 类可以等待一个信号出现(WaitOne()方法)、等待必须发出信号的多个对象(WaitAll()方法)、或者等待多个对象中的一个(WaitAny()方法)。后两者事WaitHandle类的静态方法,接收一个WaitHandle参数数组。
六::Mutex类
Mutex(mutual exclusion,互斥)是 .NET Framework中提供跨多个进程同步访问的一个类。所以,它常被用于“程序单一启动控制”。
/// <summary>
/// 单一进程 检查,如果已经运行一个进程,返回false,表示检查不通过。否则返回true。
/// </summary>
/// <returns></returns>
private bool RunOnceCheck()
{
bool vExist;
Mutex nMutex = new Mutex(false, "SingletonWinAppMutex", out vExist);
if (!vExist)
{
// 表示已经启动一个了,应退出当前启动
return false;
}
return true;
}
它非常类似于Monitor类,因为他们都只有一个线程能拥有锁定。只有一个线程能获得互斥锁定,访问受互斥保护的同步代码区域。Mutex派生自基类WaitHandle,因此可以利用WaitOne()方法获得互斥锁定,在该过程中成为该互斥的拥有者。调用 ReleaseMutex()方法,释放互斥。
bool createdNew;
Mutex mutex = new Mutex(false, "ProCSharpMutex", out createdNew); if (mutex.WaitOne())
{
try
{
// synchronized region
}
finally
{
mutex.ReleaseMutex();
}
}
else
{
// some problem happened while waiting
}
七::Semaphore类
Semaphore非常类似于互斥,其区别在于Semaphore可以同时由多个线程使用。它是一种计数互斥锁定,可以定义允许同时访问受其锁定保护的资源的线程个数。它适用于:有许多可用资源,且只允许一定数量的线程访问该资源。
八::Events类
它是一种可以在系统范围内同步资源的方法。
九::Barrier类
它非常适用于其中工作有很多个任务分支且以后又需要合并工作的情况。
十::ReaderWriterLockSlim类
为了使锁定机制允许锁定多个读取器(而不是一个写入器)访问某个资源,可以使用此类。它提供了一个锁定功能,如果没有写入器锁定资源,就允许多个读取器访问资源,但只能有一个写入器锁定该资源。
C# 多线程之线程同步的更多相关文章
- C#多线程之线程同步篇3
在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...
- C#多线程之线程同步篇2
在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...
- C#多线程之线程同步篇1
在多线程(线程同步)中,我们将学习多线程中操作共享资源的技术,学习到的知识点如下所示: 执行基本的原子操作 使用Mutex构造 使用SemaphoreSlim构造 使用AutoResetEvent构造 ...
- 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock
[源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...
- 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent
[源码下载] 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEve ...
- IOS 多线程,线程同步的三种方式
本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...
- 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)
Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...
- Java:多线程,线程同步,同步锁(Lock)的使用(ReentrantLock、ReentrantReadWriteLock)
关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨Lock对象. synchronize ...
- MFC——9.多线程与线程同步
Lesson9:多线程与线程同步 程序.进程和线程是操作系统的重点,在计算机编程中.多线程技术是提高程序性能的重要手段. 本文主要解说操作系统中程序.进程和线程之间的关系,并通过相互排斥对象和事件对象 ...
- Java多线程 3 线程同步
在之前,已经学习到了线程的创建和状态控制,但是每个线程之间几乎都没有什么太大的联系.可是有的时候,可能存在多个线程多同一个数据进行操作,这样,可能就会引用各种奇怪的问题.现在就来学习多线程对数据访问的 ...
随机推荐
- 搭建TensorFlow
网上有许多在线安装TensorFlow框架的,我试了好多,结果安装时间长先不说,还总是出现一些问题,然后我就想着离线安装,成功了,与大家分享! (1)首先,需要下载离线安装的TensorFlow包,可 ...
- Educational Codeforces Round 61 (Rated for Div. 2)D(二分,模拟,思维)
#include<bits/stdc++.h>using namespace std;typedef long long ll;int n,k;ll a[200007],b[200007] ...
- 【转】在Asp.net前台和后台弹出提示框
源地址:http://blog.sina.com.cn/s/blog_5200dd680100mkk0.html
- CI框架定义判断POST GET AJAX
CI框架当中并没有提供,类似tp框架中IS_POST,IS_AJAX,IS_GET的方法. 所有就得我们自己造轮子了.下面就介绍一下,如何定义这些判断请求的方法.其实很简单的. 首先打开constan ...
- 开窗函数Over用法
比如我们有这个表: 销售记录表 日期 姓名 产品 销售额 201601 A 电脑 12560 201601 A 手机 6501 201601 A 平板 8510 201602 A 手机 1560 20 ...
- P3978 [TJOI2015]概率论
\(\color{#0066ff}{ 题目描述 }\) 为了提高智商,ZJY开始学习概率论.有一天,她想到了这样一个问题:对于一棵随机生成的n个结点的有根二叉树(所有互相不同构的形态等概率出现),它的 ...
- 9.path Sum III(路径和 III)
Level: Easy 题目描述: You are given a binary tree in which each node contains an integer value. Find t ...
- Git的安装使用
1.什么是Git Git是一个自由和开源的分布式版本管理工具,用于有效.高速的处理任何或大或小的项目.最初由Linux Torvalds编写,用于帮助管理Linux内核开发而开发的一个开放源码的版本管 ...
- P4824 [USACO15FEB]Censoring (Silver) 审查(银)
传送门 一个串的匹配肯定考虑KMP 那就暴力KMP 记录一下到每个字符时匹配的位置 找到一个符合的串就标记然后暴力回跳 感觉好像太暴力了... #include<iostream> #in ...
- 8.11zju集训日记
今天的比赛打得很不好,前一个小时的看的题目都非常难,没有做出题目,中期看到两道题,一道题是我读题,金大佬solo的,另外一道题是金大佬读题,写了代码但wa了,然后我和zz找bug,最后发现答案的范围是 ...