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

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. CSS链接使用伪类的顺序

    顺序为:link-visited-hover-active a:link {color: #FF0000} /* 未访问的链接 */ a:visited {color: #00FF00} /* 已访问 ...

  2. Nginx 详细介绍

    Nginx 和 Apache 一样是 http 服务器软件.它们的区别是 Apache 的处理速度慢,占用内存资源, nginx 恰恰相反.在功能上 Apache 的所有模块都支持动和静态编译,而 n ...

  3. python初步学习

    一.字符编码 ASCII表是是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言,其最多只能用 8 位来表示(一个字节),即:2**8 = 256-1,所以,ASCII码最多只能表示 ...

  4. Oracle 9i,10g,11g各自alert日志的位置

    10g&9i的alert日志: 进入oracle:[zhangshengdong@oralocal1 ~]$ sudo su - oracle[oracle@oralocal1 ~]$ sql ...

  5. shell之文本过滤(grep)

    shell之文本过滤(grep) 分类: linux shell脚本学习2012-09-14 14:17 588人阅读 评论(0) 收藏 举报 shell正则表达式扩展工具存储 grep(全局正则表达 ...

  6. margin-top百分比问题

    (1)其实margin-top和margin-bottom的百分比,一般是按容器元素的宽度而不是高度来计算的,padding同理.

  7. Mysql数据库常见试题

    引用自http://blog.csdn.net/laoniyouxi123/article/details/51161157 sql语句应该考虑哪些安全性? 答: (1)防止sql注入,对特殊字符进行 ...

  8. 【bzoj3566】 [SHOI2014]概率充电器

    *题目描述: 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器: “采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可 ...

  9. urllib2之开放代理与私密代理

    1.开放代理 import urllib2 #构建代理对象 httpproxy_handler = urllib2.ProxyHandler({'http':'填入代理IP'}) #构建opener对 ...

  10. div的文字倾斜

    最近要写一个页面,需要一排文字是倾斜的,我就写了一下 <div class="qingx">倾斜导航</div> div.qingx{ -moz-trans ...