线程:线程是进程的独立执行单元,每一个进程都有一个主线程,除了主线程可以包含其他的线程。
多线程的意义:多线程有助于改善程序的总体响应性,提高CPU的效率。
多线程的应用程序域是相当不稳定的,因为多个线程在同一时间内都能运行共享的功能模块。为了保护应用程序的资源不被破坏,为多线程程序提供了三种加锁的机制,分别是:Monitor类、Lock关键字和Mutex类。
1. lock
lock实现的功能是:使后进入的线程不会中断当前的线程,而是等待当前线程结束后再继续执行。
应用:
代码如下:

private Object thisLock=new object();
lock(thisLock){
//锁定的代码块
}

注意:避免锁定 public 类型,否则实例将超出代码的控制范围。
常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock")
违反此准则:如果实例可以被公共访问,将出现 lock (this) 问题。
如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。
下面举例说明lock的应用:
下面的例子中创建了5个次线程,次线程完成的任务就是:输出线程编码,延迟1秒,然后输出当时的时间
Example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace ConsoleAppThread
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("程序开始时间:" + DateTime.Now.ToString());
Example ex = new Example();
Thread[] threads = new Thread[];
Console.WriteLine("主线程创建子线程 开始。。。。" + DateTime.Now.ToString());
for (int i = ; i < ; i++)
{
threads[i] = new Thread(new ThreadStart(ex.OutPut));
threads[i].Name = string.Format("Worker thread#{0}", i);
}
Console.WriteLine("主线程创建子线程 结束。。。。" + DateTime.Now.ToString());
Console.WriteLine("主线程启动子线程 开始。。" + DateTime.Now.ToString());
foreach (Thread t in threads)
{
t.Start();
}
Console.WriteLine("主线程启动子线程 结束。。" + DateTime.Now.ToString());
Console.ReadLine();
}
} class Example
{
private static object thisLock = new object();
public void OutPut()
{
//有lock lock (thisLock)
{
Console.WriteLine("->{0}", Thread.CurrentThread.Name);
Thread.Sleep();
Console.WriteLine(DateTime.Now);
} //无lock //Console.WriteLine("->{0}", Thread.CurrentThread.Name);
//Thread.Sleep(1000);
//Console.WriteLine(DateTime.Now); } }
}

实验结果如下:

图1:加lock

图2:没有lock

从实验结果可以看出,加lock后,程序每次只能执行一个线程,只有当前线程执行完了,才会执行下一个线程未加lock,程序执行混乱,容易阻塞。

2. Monitor
lock是对Monitor的Enter和Exit的一个封装,因此Monitor类的Enter()和Exit()方法的组合使用可以用lock关键字替代。
Monitor类除了具有lock的功能外,还有以下功能:
TryEnter()解决长期死等的问题,如果一个并发经常发生,并且持续时间很长,使用TryEnter,可以有效防止死锁或者长时间 的等待。
Wait()释放对象上的锁,以便允许其他线程锁定和访问该对象。在其他线程访问对象时,调用线程将等待。脉冲信号用于通知等待线程有关对象状态的更改。
Pulse(),PulseAll()向一个或多个等待线程发送信号。该信号通知等待线程锁定对象的状态已更改,并且锁的所有者准备释放该锁。等待线程被放置在对象的就绪队列中以便它可以最后接收对象锁。一旦线程拥有了锁,它就可以检查对象的新状态以查看是否达到所需状态。
注意:Pulse、PulseAll和Wait方法必须从同步的代码块内调用。

3. Mutex(互斥体)
Mutex的突出特点是可以跨应用程序域边界对资源进行独占访问,即可以用于同步不同进程中的线程,这种功能是以牺牲更多的系统资源为代价的。
互斥体Mutex和事件对象EventWaitHandler属于内核对象,利用内核对象进行线程同步,线程必须要在用户模式和内核模式间切换,所以一般效率很低,但利用互斥对象和事件对象这样的内核对象,可以在多个进程中的各个线程间进行同步。
互斥体Mutex类似于一个接力棒,拿到接力棒的线程才可以开始跑,当然接力棒一次只属于一个线程(Thread Affinity),如果这个线程不释放接力棒(Mutex.ReleaseMutex),那么其他所有需要接力棒运行的线程只能等着看热闹。

C#中Monitor类、Lock关键字和Mutex类的更多相关文章

  1. Thread锁 Monitor类、Lock关键字和Mutex类

    Monitor 类锁定一个对象 当多线程公用一个对象时,也会出现和公用代码类似的问题,这种问题就不应该使用lock关键字了,这里需要用到System.Threading中的一个类Monitor,我们可 ...

  2. 锁、C#中Monitor和Lock以及区别

    1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取锁之后因为异常,致锁 ...

  3. C#知识点总结系列:4、C#中Monitor和Lock以及区别

    Monitor对象 1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取 ...

  4. C#中Monitor和Lock以及区别

    Monitor对象 1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取 ...

  5. Java中Super和final关键字以及异常类

    1.final类不能有子类,也就谈不上继承的说法,如果用final修饰成员变量或者局部变量,那成了常量需要制定常量的值. 2.对象的上转型对象,上转型对象不能操作子类新增的成员变量,不能调用子类新增的 ...

  6. C#使用Monitor类、Lock和Mutex类进行多线程同步

    在多线程中,为了使数据保持一致性必须要对数据或是访问数据的函数加锁,在数据库中这是很常见的,但是在程序中由于大部分都是单线程的程序,所以没有加锁的必要,但是在多线程中,为了保持数据的同步,一定要加锁, ...

  7. C#中Monitor对象与Lock关键字的区别分析

    这篇文章主要介绍了C#中Monitor对象与Lock关键字的区别,需要的朋友可以参考下 Monitor对象 1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(ob ...

  8. 转:C#中Monitor对象与Lock关键字的区别分析

    Monitor对象1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取 ...

  9. C#中的lock关键字有何作用

    作为C#的程序员来说,在遇到线程同步的需求时最常用的就是lock关键字.但如何正确并有效地使用lock,却是能否高效地达到同步要求的关键.正因为如此,程序员需要完全理解lock究竟为程序做了什么. 所 ...

随机推荐

  1. ADO.NET 增、删、改、查

    ADO.NET:数据访问技术 就是将C#和MSSQL连接起来的一个纽带 可以通过ADO.NET将内存中的临时数据写入到数据库中也可以将数据库中的数据提取到内存中供程序调用 所有数据访问技术的基础 连接 ...

  2. PHP的三种输出方式

    (1)echo 是PHP语句,没有返回值,用于输出一个或多个字符串 (2)print() 是函数,可以有返回值,只能打印出简单类型变量的值,例如int.string (3)print_r() 是函数, ...

  3. Question and Answer

    1.VS2013使用EntityFrame问题解决办法 解决办法参照博客http://pinter.org/?p=2374 使用到EntityFrame的项目配置文件修改如下: 项目中凡是使用到DbC ...

  4. HDU 1372 Knight Moves

    最近在学习广搜  这道题同样是一道简单广搜题=0= 题意:(百度复制粘贴0.0) 题意:给出骑士的骑士位置和目标位置,计算骑士要走多少步 思路:首先要做这道题必须要理解国际象棋中骑士的走法,国际象棋中 ...

  5. codeforces 451E Devu and Flowers

    题意:有n个瓶子每个瓶子有 f[i] 支相同的颜色的花(不同瓶子颜色不同,相同瓶子花视为相同) 问要取出s支花有多少种不同方案. 思路: 如果每个瓶子的花有无穷多.那么这个问题可以转化为  s支花分到 ...

  6. sprintf函数

    sprintf函数用法举例 #include<stdio.h> int main() { //1.连接字符串 char a1[] = {'A', 'B', 'C', 'D', 'E', ' ...

  7. Android Performance Optimization

    1.zipalign 2.ui优化 3.package size 4.RenderScript 5.Resource Shrinking & Code Shrinking 6.java cod ...

  8. 进监狱全攻略之 Mifare1 Card 破解

    补充新闻:程序员黑餐馆系统 给自己饭卡里充钱 ,技术是双刃剑,小心,小心! 前言 从M1卡的验证漏洞被发现到现今,破解设备层出不穷,所以快速傻瓜式一键破解不是本文的重点,年轻司机将从本文中获得如下技能 ...

  9. React Native的组件ListView

    React Native的组件ListView类似于iOS中的UITableView和UICollectionView,也就是说React Native的组件ListView既可以实现UITableV ...

  10. .Net内存泄露原因及解决办法

    .Net内存泄露原因及解决办法 1.    什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈.非托管堆和托管堆.这里我们需 ...