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

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. Hive配置日志

    1. 重命名hive/conf文件夹下的hive-log4j 2. 修改hive.log.dir参数,如果不修改默认hive.log位于/tmp/{user}下面,一般来说使用在hive目录下自己创建 ...

  2. 31. Next Permutation (JAVA)

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  3. C# Base64加解密

    using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptograph ...

  4. Nginx服务项的基本配置

    由于Nginx配置项较多,把他们按照用户使用时的预期功能分为以下4类: 1.调试,定位问题的配置项 2.正常运行必备配置项 3.优化性能配置项 4.事件类配置项 1. 用于调试进程,定位问题的配置项 ...

  5. CentOS7 添加新用户并授权 root 权限

    参考文章:CentOS 7中添加一个新用户并授权 # root 用户操作 $ 普通用户操作 创建用户 # adduser USERNAME # passwd USERNAME (输入密码) 授权 ro ...

  6. springboot之学习搭建

    什么是**SpringBoot?** Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配 ...

  7. win10文件夹共享

    1.开启server服务就可以使用net share 命令 2.查看目前已共享的文件夹 3.关闭默认共享 只有用administrator(且有密码)才能连上win10上的默认共享了,只有admini ...

  8. grandson定理

    用处:求解同余线性方程组 inv:逆元 一堆物品 3个3个分剩2个 5个5个分剩3个 7个7个分剩2个 问这个物品有多少个 5*7*inv(5*7,  3) % 3  =  1 3*7*inv(3*7 ...

  9. vue-jwt 实战

    作用:把用户的信息储存到客户端 每次客户端带上token 校验是否登陆过 1.使用主要有两个api jwt.sign(payload, secretOrPrivateKey, [options, ca ...

  10. Azure IoT 技术研究系列4

    上两篇博文中,我们介绍了将设备注册到Azure IoT Hub,设备到云.云到设备之间的通信: Azure IoT 技术研究系列2-设备注册到Azure IoT Hub Azure IoT 技术研究系 ...