复习及总结--.Net线程篇(4)
这里要说的就是多线程的锁的问题了
锁:作用在于实现线程间的同步问题,最典型的是售票问题
1,InterLocked
提供的都是静态方法,用来同步对多个共享变量的访问,包括以原子方式递增,递减,比较和替换值得方法
原子操作:方法在一个操作中完成它的功能的操作,递增操作分为两步进行,1,植被增加,2更新值被存储
静态方法
Long Increment(ref long value)
int Increment(ref int value)
递增指定的值,然后返回更新后的值
int Decrement(ref int value)
long Decrement(ref long value)
递减指定的值,然后返回更新后的值
int Exchange(ref int location ,int newvalue) 其他的重载还有float,Object
把location的值设置为newvalue,可以交换整型值,单精度和对象类型返回location的原始值
CompareExchange(ref object destvalue,object replacevalue,object compareValue)
比较destvalue和comparevalue 如果值相同,destvalue用replacevalue代替 返回destvalue的值
监控器锁
Method1 Monitor.Enter(obj) 获取锁 Monitor.Waite(obj) 阻塞当前线程 Monitor.Exite(obj) 释放锁 Method2 Monitor.Enter(obj) 获取锁 Monitor.Pulse(obj) 唤醒Method1中Waite的线程 Monitor.Exite(obj) 释放锁
Monitor 类使用锁的概念提供对象的同步代码块,监控锁和临界区相似,只有拥有对象监控锁的对象才能访问对象
Enter(object obj)
视图获得指定对象的监控锁,如果另一个线程持有锁,该方法会阻塞,如果obj为空则抛出异常
Exite(object obj)
释放指定对象的监控器锁,现在,另一个线程就可以获得锁了,若果obj为空,或者当前线程并不持有指定对象的锁,系统将抛出异常
Pulse(object obj)
被持有指定对象的锁的线程调用,以通知等待队列中的下一个线程在对象状态方面的变化,这下一个线程被移预备队列中,调用
Pluse方法的线程释放锁,允许预备队列中下一个线程获得该锁,该方法必须从一个同步代码块中调用,如果Obj是空引用则抛异常
PulseAll(Object obj)
被持有指定对象的锁的线程调用,以通知等待队列的所有线程在对象状态方面的变化,等待队列中的所有线程被移到预备队列中,调用
PluseAll方法的线程释放锁,允许预备队列中的下一个线程获取到该锁,该方法必须从一个同步代码块中调用,同上抛出异常
TryEnter(Object obj)
视图在特定的雕件下获取指定对象的监控锁,第一个版本在视图获取锁时不会阻塞,第二个和第三个版本就会阻塞,但值阻塞指定的时间间隔,如果方法成功返回true,否则返回false
wait(Object obj)
释放监控器锁并把调用线程放在等待队列中,如果另一个线程调用了pulse和pulseall方法该线程被移到预备队列中
class Program
{ Queue queue = new Queue(); static void Main(string[] args)
{
Program p = new Program();
Thread t1= new Thread(p.Add);
Thread t2= new Thread(p.Remove);
t2.Priority = ThreadPriority.Highest;
t1.Start();
t2.Start(); Console.ReadKey();
} public void Add()
{
for (int i = ; i < ; i++)
{
Monitor.Enter(queue); this.queue.Enqueue(i); Console.WriteLine("当前数组数量:" + queue.Count); Monitor.Pulse(queue); Monitor.Exit(queue);
}
} public void Remove()
{ for (int i = ; i < ; i++)
{
lock (queue)
{
if (queue.Count < )
Monitor.Wait(queue);
queue.Dequeue(); }
}
}
WaitHandle类
是Win32同步句柄的基类,它用来管理对共享资源的访问,它提供了等待直到对象变为有新号状态的方法
派生类 Mutex,AutoResetEvent,ManualResetEvent
InvalidHandle 代表一个无效的同步句柄
WaitTimeout敞亮是一个整形,之处对WaitAny方法的调用已经超时
属性
Handle 访问和设置本机操作系统句柄
公共静态方法
WaitAll(WaitHandle[] waitHandles)
当指定数组中的所有waithandle对象变为有信号状态时,或者指定的超时时间已到,WaitAll返回
WaitAny (WaitHandle[] waitHandles)
当指定数组中的任意waithandle对象变为有信号状态时,或者指定的超时时间已到,WaitAny返回
Close()
关闭调用句柄,该方法调用Dispose方法,传递给他一个ture
WaitOne()-------请求互斥锁
在调用WaitHandle对象处于有信号状态,或者指定超时时间已到时返回。无参的签名将无限期阻塞
直到当前的WaitHandle变为有信号状态,如果WaitHandle是空引用则抛异常
Mutex类
代表一个允许排斥访问共享资源的互斥锁,一旦一个线程获得了互斥锁,想访问共享资源的任何其他线程就被挂起直到锁被释放。WaitHandle类的WaitOne方法可以用来请求互斥锁。可以调用ReleaseMutex方法来释放锁
ReleaseMutex方法释放一次互斥锁,也就是说调用了几次Wait()方法,就需要调用几次ReleaseMutex方法
class MutexDemo
{
private Mutex mutex = new Mutex(); public MutexDemo()
{
mutex = new Mutex();
} public static void Run()
{
MutexDemo demo = new MutexDemo();
Thread th1 = new Thread(demo.Increment);
Thread th2 = new Thread(demo.Increment); th1.Name = "One";
th2.Name = "Two"; th1.Start();
th2.Start(); Console.ReadKey(); } public void Increment()
{
for (int i = ; i < ; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + "--" + i);
Thread.Sleep();
}
}
结果为
One--0
Two--0
One--1
Two--1
One--2
Two--2
One--3
Two--3
我们想要的是让第一个线程打印完然后去打印第二个线程,那么
class MutexDemo
{
private Mutex mutex = new Mutex(); public MutexDemo()
{
mutex = new Mutex();
} public static void Run()
{
MutexDemo demo = new MutexDemo();
Thread th1 = new Thread(demo.Increment);
Thread th2 = new Thread(demo.Increment); th1.Name = "One";
th2.Name = "Two"; th1.Start();
th2.Start(); Console.ReadKey(); } public void Increment()
{
mutex.WaitOne();
for (int i = ; i < ; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + "--" + i);
Thread.Sleep();
}
mutex.ReleaseMutex();
}
这样的结果就是我们想要的了
ReaderWriterLock类
该类为读写数据的线程提供锁,它支持嵌套的读锁和写锁,并允许宁改变与线程关联的类型,或者把锁回复到前一个状态,ReaderWriterLock对象可以获得一个读锁或者一个写锁,但不能同时获得两个锁。ReaderWriterLock对象能够支持至少一个写线程,但可支持多个读线程
属性
bool IsReaderLockHeld
bool IsWriterLockHeld
int WriterSeqNum
如果当前线程持有读锁,IsReaderLockHeld返回true;
如果当前线程持有写锁,IsWriterLockHeld返回true
WriterSeqNum检索和ReaderWriterLock相关的序列号,如果ReaderWriterLock没有获得写锁,序列号就是1,如果获得了,序列号就是2
void AcquireReaderLock()
AcquireReaderLock视图为当前线程获得读锁,他将在指定的事件内进行操作,该方法支持嵌套的读锁,如果另一个线程有写锁,调用线程将阻塞
void AcquireWriterLcok()
AcquireWriterLcok 视图为当前线程获得写锁,在指定的事件内进行这个操作,该方法支持嵌套的写锁,如果另一个线程有读锁,调用线程将阻塞,如果他本身持有读锁,将造成死锁,可以使用UpgradeToWriterLock方法防止死锁的出现
AnyWritersSince(int seqNum)
如果自从获得该实例的序列号以来发生了任何中间写操作,AnyWritersSince返回true
ReleaseLock
ReleaseReaderLock
ReleaseWriterLock
释放锁的方法
class RWDemo
{
ReaderWriterLock rwlock;
int value;
byte[] buf = new byte[];
MemoryStream ms; public RWDemo()
{
rwlock=new ReaderWriterLock();
value = ;
ms = new MemoryStream(); } public static void Run()
{
RWDemo demo = new RWDemo(); Thread one = new Thread(demo.ReadSome);
Thread two = new Thread(demo.ReadSome);
Thread three = new Thread(demo.WriteSome); one.Start();
two.Start();
three.Start(); } public void WriteSome()
{
rwlock.AcquireReaderLock(-);
Thread.Sleep();
buf[] = (byte)value;
ms.Position = ;
ms.Write(buf, , buf.Length);
Console.WriteLine("value write is "+value);
rwlock.ReleaseReaderLock();
} public void ReadSome()
{
Thread.Sleep();
rwlock.AcquireWriterLock(-);
ms.Position = ;
Console.WriteLine("value read is " + ms.ReadByte());
rwlock.ReleaseWriterLock();
}
}
复习及总结--.Net线程篇(4)的更多相关文章
- 复习及总结--.Net线程篇(3)
不幸的发现,原来多线程的东西还有好多. 不只是一个Thread就能把事情做完的,好吧,孤陋寡闻了 这里总结下 复习及总结--.Net线程篇(2)里的两个概念AppDomain和ThreadPool ...
- 复习及总结--.Net线程篇(2)
复习总结 上一篇里讲到了使用委托异步调用的方式来使用多线程,这里介绍几个概念 这里贴出来一个关于应用程序域的帖子 http://www.cnblogs.com/firstyi/archive/2008 ...
- 复习及总结--.Net线程篇(1)
老是没耐心写这些东西,最近想想也工作两年了,该对自己的东西做个整理了,不知道这次能坚持写几篇,总得来说尽量督促自己吧 言归正传,.net中的多线程主要可以使用两种方法进行调用 1,异步调用 2,Thr ...
- JAVA技术专题综述之线程篇(1)
本文详细介绍JAVA技术专题综述之线程篇 编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield( ...
- Java面试知识点之线程篇(三)
前言:这里继续对java线程相关知识点进行总结,不能间断. 1.yield()方法 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执 ...
- Java面试知识点之线程篇(二)
前言:接上篇,这里继续对java线程相关知识点进行总结. 1.notify和notifyall的区别 notify()方法能够唤醒一个正在等待该对象的monitor的线程,当有多个线程都在等待该对象的 ...
- Java面试知识点之线程篇(一)
前言:在Java面试中,一定会遇到线程相关问题,因此笔者在这里总结Java中有关线程方面知识点,多数从网上得来(文中会贴出主要参考链接),有些也是笔者在面试中所遇到的问题,如有错误,请不吝指正.主要参 ...
- Python3 与 C# 并发编程之~ 线程篇
2.线程篇¶ 在线预览:https://github.lesschina.com/python/base/concurrency/3.并发编程-线程篇.html 示例代码:https://gith ...
- 【转】C#线程篇
C# 温故而知新: 线程篇(一) C# 温故而知新: 线程篇(二) C# 温故而知新:线程篇(三) C# 温故而知新: 线程篇(四)
随机推荐
- 总结js(Iframe、window.open、window.showModalDialog)父窗口与子窗口之间的操作
http://hi.baidu.com/yashua839/blog/item/131fdb2fe547ef221f3089af.html一.Iframe 篇 //&&&&am ...
- maven打包到本地仓库里面
mvn install:install-file -Dfile=D:/你的包名 -DgroupId=com.sdk4j -DartifactId=sdk4j -Dversion=1.0 -Dpack ...
- JAVA中的字节流与字符流
字节流与字符流的区别? 字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用 ...
- 火狐浏览器(firefox)中js要注意的问题
1.出现错误调用error方法或者ajax请求了多次,那么极有可能是异步请求的原因. 添加 async : false , -> async. 默认是 true,即为异步方式,$.aja ...
- python pivot() 函数
以下为python pandas 库的dataframe pivot()函数的官方文档: Reshape data (produce a “pivot” table) based on column ...
- screen常用命令
1. 背景 由于经常使用ssh登录实验室的服务器训练神经网络, 而一些复杂的神经网络模型需要长时间训练,在此期间,如果出现网络等原因出现链接中断的话,服务器的进程也会被杀死,之前的一切半途而废.利用s ...
- blender, merge顶点
选择Edit Mode:,和vertex select: 同时选中两个要merge的顶点(同时选中多个顶点:http://www.cnblogs.com/wantnon/p/4526573.html) ...
- atitit.研发管理--标准化流程总结---java开发环境与项目部署环境的搭建工具包总结
atitit.研发管理--标准化流程总结---java开发环境与项目部署环境的搭建工具包总结 1. ide系列(只开发环境需要,但部署环境也做好放上,很有用) 1 2. web服务器+sdk+网站程序 ...
- Launcher代码大全
蜂窝网络:prefs:root=MOBILE_DATA_SETTINGS_ID VPN:prefs:root=General&path=Network/VPN Wi-Fi:prefs:root ...
- 基于jQuery左侧小图滚动右侧大图显示代码
今天给大家分享一款 jQuery左侧小图滚动右侧大图显示代码是一款基于jQuery实现的左侧滚动图片点击大图查看效果代码.该实例适用浏览器:IE8.360.FireFox.Chrome.Safari. ...