之前的博文也说到了如果多线程对于访问的公共资源操作都是原子操作,那么可以避免竞争条件。关于多线程的竞争可以百度。

1.执行最基本的原子操作

c#提供了一系列供我们使用的原子操作的方法和类型,比如我们的自增和自减操作。

看代码

class Program
{
private static int _count = ;
static void Main(string[] args)
{
var thread1 = new Thread(() =>
{
for(int i = ; i < ; i++)
{
Operation();
}
});
var thread2 = new Thread(() =>
{
for (int i = ; i < ; i++)
{
Operation();
}
});
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine(_count);
Console.Read();
}
public static void Operation()
{
//自增
_count ++;
_count--;
}

上面的代码还是会引起竞争条件问题,所以并不是线程安全的,我们可以使用c#提供的Interlocked进行自增,自减等操作,并且是原子性的。

对上面程序进行改动

private static int _count = ;
static void Main(string[] args)
{
var thread1 = new Thread(() =>
{
for(int i = ; i < ; i++)
{
Operation();
}
});
var thread2 = new Thread(() =>
{
for (int i = ; i < ; i++)
{
Operation();
}
});
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine(_count);
Console.Read();
}
public static void Operation()
{
//自增
Interlocked.Increment(ref _count);
Interlocked.Decrement(ref _count);
}

结果就是正确的了。

2.Metux类(互斥量)

Mutex是一种原始的在线程同步方式,它只对一个线程授予共享资源的独占访问,并且它是操作系统全局的,所以它更大的场景用于不同程序之间多线程的同步

它的几个构造方法在上图中。

Mutex():这是比较特殊的,用的很少的构造方法,因为之前说Mutex是一个操作系统全局的互斥量,但是需要根据名字来使用,这种构造方法是匿名的,所以可以称作局部互斥量。

Mutex(bool initiallyOwned):传入的bool值表示创建者是否立刻拥有该互斥量

Mutex(bool initiallyOwned,string name):与上面的区别就是拥有名字,可以在去他程序中被使用。

Mutex(bool initiallyOwned,string name,out bool createNew):第三个out参数用于表明是否获得了初始的拥有权。这个构造函数应该是我们在实际中使用较多的。

Mutex(bool initiallyOwned,string name,out bool createNew,MuteSecurity muteSecurity):第四个参数是对于Mutex的一些安全设置,详见MSDN

说这么多我们先来一个例子来看看如何使用Mutex

private static readonly string MutexName = "GLOBAL_MUTEX";
static void Main(string[] args)
{
var thread = new Thread(() => { Operations(); });
thread.Start();
Operations(); Console.ReadLine();
} public static void Operations()
{
bool result;
using (var mutex = new Mutex(false, MutexName,out result))
{
try
{
if (mutex.WaitOne(TimeSpan.FromSeconds(), false))
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Instance is running");
Thread.Sleep();
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Instance is Exiting");
}
}
catch
{ }
finally
{
mutex.ReleaseMutex();
} }
}

这段代码其实就是看主线程和子线程谁先拿到互斥量,就可以先执行,另外一个线程就会等待它执行完再去执行。所以结果如下。

我们稍微改动一下代码。

private static readonly string MutexName = "GLOBAL_MUTEX";
static void Main(string[] args)
{
var thread = new Thread(() => { Operations(); });
thread.Start();
Operations(); Console.ReadLine();
} public static void Operations()
{
bool result;
using (var mutex = new Mutex(false, MutexName,out result))
{
try
{
if (mutex.WaitOne(TimeSpan.FromSeconds(), false))
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Instance is running");
Thread.Sleep();
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Instance is Exiting");
mutex.ReleaseMutex();
}
else
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Instance is waitting out of time");
}
}
catch
{
Console.WriteLine("error");
}
finally
{ } }
}

增加一点时间延迟,因为我们设置了5s的等待,但是主体时间超过6s,所以必将会有线程等待超时。

那么可能会有人问了,那他和上一节的monitor到底有何区别?其实最大的区别也提到过了,就是它是操作系统全局的。具体细节可以参考园子里这篇文章,写的比我详细很多。

https://www.cnblogs.com/suntp/p/8258488.html

最后就是因为Mutex对象是操作系统全局的,一定要正确关闭释放它。

c# Thread5——线程同步之基本原子操作。Mutex互斥量的使用的更多相关文章

  1. 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock

    [源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...

  2. Linux并发与同步专题 (4) Mutex互斥量

    关键词:mutex.MCS.OSQ. <Linux并发与同步专题 (1)原子操作和内存屏障> <Linux并发与同步专题 (2)spinlock> <Linux并发与同步 ...

  3. [一个经典的多线程同步问题]解决方案三:互斥量Mutex

    本篇通过互斥量来解决线程的同步,学习其中的一些知识. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互 ...

  4. 【Linux】Mutex互斥量线程同步的例子

    0.互斥量  Windows下的互斥量 是个内核对象,每次WaitForSingleObject和ReleaseMutex时都会检查当前线程ID和占有互斥量的线程ID是否一致. 当多次Wait**时就 ...

  5. C++多线程同步之Mutex(互斥量)

    原文链接: http://blog.csdn.net/olansefengye1/article/details/53086141 一.互斥量Mutex同步多线程 1.Win32平台 相关函数和头文件 ...

  6. 基元线程同步构造之 Mutes(互斥体)

    互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)). 互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section). 因 ...

  7. Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

    互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...

  8. php Pthread 多线程 (三) Mutex 互斥量

    当我们用多线程操作同一个资源时,在同一时间内只能有一个线程能够对资源进行操作,这时就需要用到互斥量了.比如我们对同一个文件进行读写操作时. <?php class Add extends Thr ...

  9. mutex 互斥量

    有用参考:http://blog.csdn.net/yl2isoft/article/details/46003467 摘抄记录:using System.Threading; class Examp ...

随机推荐

  1. 我国三大常用坐标系:北京54、西安80和WGS-84

    转自:http://blog.sina.com.cn/s/blog_6dbe2d780100mwr5.html 我国三大常用坐标系:北京54.西安80和WGS-84 1.北京54坐标系(BJZ54)北 ...

  2. Python 计算Numpy向量之间的欧氏距离

    vector1 = np.array([1,2,3]) vector2 = np.array([4,5,6]) dist = numpy.sqrt(numpy.sum(numpy.square(vec ...

  3. 008-流程控制 case 语句

    流程控制 case 语句 与if...elif...else 语句一样都是多分支条件语句,不过if语句可以判断多种条件关系,case只能判断一种条件关系 [root@zabbix lianxi]# . ...

  4. vue项目中使用swiper插件遇到的坑

    <style scoped> .swiper-pagination-bullets  >>> .swiper-pagination-bullet-active {     ...

  5. kubernetes之三 使用kubectl在k8s上部署应用

    在上一篇中,我们学习了使用minikube来搭建k8s集群.k8s集群启动后,就可以在上面部署应用了.本篇,我们就来学习如何使用kubectl在k8s上部署应用. 学习之前,可以先从下面这篇博客上了解 ...

  6. 造个自己的Vue的UI组件库类似Element

    前言 随着前端的三大框架的出现,组件化的思想越来越流行,出现许多组件库.它能够帮助开发者节省时间提高效率, 如React的Ant-design,Vue的iView,Element等,它们的功能已经很完 ...

  7. Nacos 快速开始

    原文:https://nacos.io/zh-cn/docs/quick-start.html https://www.jianshu.com/p/16ff6d6db0cf Nacos安装: 1.从 ...

  8. Django【第20篇】:Ajax

    初始Ajax 一.Ajax准备知识:json 说起json,我们大家都了解,就是python中的json模块,那么json模块具体是什么呢?那我们现在详细的来说明一下 1.json(Javascrip ...

  9. Centos 6.4 x86_64 最小化安装后的优化——还需要整理

      Centos 6.4 x86_64 最小化安装后的优化   购买了服务器以后要做的第一件事就是安装操作系统了,这里推荐安装 Centos 6.4 x86_64,安装系统时要选择最小化安装(不需要图 ...

  10. KCF跟踪算法

    参考:https://www.cnblogs.com/YiXiaoZhou/p/5925019.html 参考:https://blog.csdn.net/shenxiaolu1984/article ...