复习及总结--.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# 温故而知新: 线程篇(四)
随机推荐
- 安装 percona-xtrabackup 2.4
Installing Percona XtraBackup from Percona yum repository Install the Percona repository You can ins ...
- Python爬虫实战案例:爬取爱奇艺VIP视频
一.实战背景 爱奇艺的VIP视频只有会员能看,普通用户只能看前6分钟.比如加勒比海盗5的URL:http://www.iqiyi.com/v_19rr7qhfg0.html#vfrm=19-9-0-1 ...
- 破解Aspose 操作pdf word等文档 对10以下版本有效
using System; using System.IO; namespace LicenseHelper { public static class License { public const ...
- C++中四种类型转换以及const_cast是否能改变常量的问题
we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...
- nginx Beginner’s Guide
这个引导给nginx做了一个基本的介绍,并描述了nginx可以做的一些基本事情. 假设nginx已经安装在了读者的电脑上,如果没有请查看官网安装页. 这个引导描述了怎么去开始和结束nginx,从新加载 ...
- iOS图片上传及处理
从摄像头或者是从相冊中读取图片.须要通过UIImagePickerController类来实现,在使用UIImagePickerController时,须要是实现以下两个协议 <UINaviga ...
- union共用体的对齐
union DATE { char a; ]; double b; }; DATE max; cout<< sizeof(max) << endl; 这个问题很好回答,并且我把 ...
- MySQL5.0存储过程教程
Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了“存储过程.触发器.视图.信息架构视图”,在此感谢译者陈朋奕的努力 ...
- Memcached安装以及PHP的调用
Memcached安装以及PHP的调用 [南京·10月17日]OSC源创会开始报名:Swift.大型移动项目构架分享 » 一:安装libevent 由于memcached安装时,需要使用libeven ...
- How to Install Xcode, Homebrew, Git, RVM, Ruby & Rails on Snow Leopard, Lion, Mountain Lion, and Mavericks
After following many outdated and incomplete instructions for setting up a web development environme ...