复习及总结--.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# 温故而知新: 线程篇(四)
随机推荐
- OAuth2.0官方文档中文翻译
http://page.renren.com/699032478/note/708597990 (一)背景知识 OAuth 2.0很可能是下一代的“用户验证和授权”标准,目前在国内还没有很靠谱的技术资 ...
- ffff表单提交的那点事
一.关于application/x-www-form-urlencoded等字符编码的解释说明 在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器 ...
- Docker背景介绍
背景介绍 Docker是PasS提供商DoctCloud开源的一个基于LXC的高级容器引擎,源代码托管在Github上,基于go语言并遵从Apache2.0协议开源.Docker近期非常火热,无论是从 ...
- [na]tcp的可靠性
- Struts2 上传下载
一. 1.文件上传是web应用经常用到的一个知识.原理是,通过为表单元素设置enctype=”multipart/form-data”属性,让表单提交的数 据以二进制编码的方式提交,在接收此请求的Se ...
- Python处理文件以及文件夹常用方法
1.创建文件并且写入 2.多行读取文件的方式 readlines() 3.一次读取全部内容 4.文件的删除 5.shutil 模块实现文件的复制 6.文件的重命名 7.获取文件的后缀名 8.pytho ...
- saveFile()方法
saveFile的原理就是将流写入到需要写入的文件,通过可以用“FileOutputStream”创建文件实例,之后过“OutputStreamWriter”流的形式进行存储,举例:public vo ...
- background-origin:规定 background-position 属性相对于什么位置来定位
background-origin:border-box;此时设置background-size:contain; 根据容器的边框定位 例如:容器的盒模型如下:设置了padding:20px;bord ...
- jQuery+html5实现的3D动态切换焦点轮播幻灯片
今天爱编程给网友们分享一款基于jQuery+html5实现的3D动态切换焦点轮播幻灯片,支持左右箭头和圆点按钮播放控制,支持多种不同的3D动态切换特效,自适应全屏显示,兼容360.FireFox.Ch ...
- PHP,JavaScript,CSS三种HTML内嵌语言的语法,变量,循环,函数记录
PHP PHP简介: PHP 是服务器端脚本语言. PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一种通用开源脚本语言. PH ...