.NET开发中多线程的使用

发布时间:2021-07-12 17:12:14 作者:chen
来源:亿速云 阅读:114

本篇内容主要讲解“.NET开发中多线程的使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“.NET开发中多线程的使用”吧!

在NET中,我们用的最多的锁机制就是lock,用起来很简单,短短几行程序就可以实现,例如:

Lock 's Code
public class TestThreading
{
private System.Object lockThis = new System.Object();
public void Function()
{
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
}

其实我们也明白,lock并不是锁,而是MS提供的一个简便式的写法,真正实现的是Monitor类中的Enter和Exit方法,既然提到了Monitor类也就说下有个需要注意的地方:

Pulse和PulseAll方法,这两个方法就是把锁状态将要改变的消息通知给等待队列中的线程,不过这时如果等待队列中没有线程,那么该方法就会一直等待下去,直到有等待的线程进入队列,也就是说该方法可能造成类试死锁的情况出现。

上面的lock + 线程(Thread和ThreadPool) = 多线程编程(N%)!?

对于该公式我曾经的N是80,现在是20。其中有很多东西影响我,让我从80->20,下面的Optex就是一个入口点。

--------------------------------------------------------------------------------

Optex 's Code
public sealed class Optex : IDisposable {
private Int32 m_Waiters = 0;
private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);

public Optex() { }
public void Dispose() {
if (m_WaiterLock != null)
{
m_WaiterLock.Close();
m_WaiterLock = null;
}
}

public void Enter() {
Thread.BeginCriticalRegion();
// Add ourself to the set of threads interested in the Optex
if (Interlocked.Increment(ref m_Waiters) == 1) {
// If we were the first thread to show interest, we got it.
return;
}

// Another thread has the Optex, we need to wait for it
m_WaiterLock.WaitOne();
// When WaitOne returns, this thread now has the Optex
}

public void Exit() {
// Subtract ourself from the set of threads interested in the Optex
if (Interlocked.Decrement(ref m_Waiters) > 0) {
// Other threads are waiting, wake 1 of them
m_WaiterLock.Release(1);
}
Thread.EndCriticalRegion();
}
}

看完上面的代码,让我增加了两点认识:

1、Thread.BeginCriticalRegion()和Thread.EndCriticalRegion();        

因为这段时间正好看了一本多线程编程的书,既然将上面方法认为是进入临界区和退出临界区,对于临界区而言,进入该区的数据,在没有退出之前,如果临界区外的程序需要使用它,那么就必须出于等待。所以觉得已经使用临界区,为什么还要使用Semaphore?!

可是,MS只是取了个相同的名字,做的事情完全不同,上面两个方法完全没有临界区的概念,它只是设置一个区域(Begin到End之间),表示该区域内发生线程中断或未处理的异常会影响整个应用程序域。

2、m_Waiters的作用

一开始以为在Enter的时候,直接写上:

m_WaiterLock.WaitOne();

Exit的时候,写上:

m_WaiterLock.Release(1);

这样就可以了。m_Waiters有什么意义?!           

优化性能,Semaphore是内核对象,我们都知道,要尽量少的进入内核模式,因为这是很消耗性能,所以尽量少的使用内核对象。m_Waiters的意义就在这里,如果只有一个线程使用该锁对象的时候,是不需要去获取和释放的。 OK,上述的东西都是铺垫,铺完了也就进入主题了!

多线程的思维

优化的Optex 

namespace ThreadConcurrent.Lock
{
public sealed class Optex : IDisposable
{
///
private Int32 m_LockState = c_lsFree;
private const Int32 c_lsFree = 0x00000000;

///
private const Int32 c_lsOwned = 0x00000001;

///
private const Int32 c_1Waiter = 0x00000002;
public Optex() { }
public void Enter()
{
Thread.BeginCriticalRegion();
while (true)
{
Int32 ls = InterlockedOr(ref m_LockState, c_lsOwned);
///[object Object]
///[object Object]
///
private static Int32 InterlockedAnd(ref Int32 target, Int32 with)
{
Int32 i, j = target;
do
{
i = j;
j = Interlocked.CompareExchange(ref target, i & with, i);
} while (i != j);
return j;
}
///[object Object]
///[object Object]
///
private static Int32 InterlockedOr(ref Int32 target, Int32 with)
{
Int32 i, j = target;
do
{
i = j;
j = Interlocked.CompareExchange(ref target, i | with, i);
} while (i != j);
return j;
}
public void Dispose()
{
if (m_WaiterLock != null)
{
m_WaiterLock.Close();
m_WaiterLock = null;
} 
}
}
}

对于上面的这个代码,我晕眩了好一段时间,不过当我真正理解的时候,从晕眩中学到了做多线程编程应该具备的思维方式。

首先从简单的理解开始谈,

1、原子化操作

对于InterLocked类,曾经也知道,但是却用的很少,不过从该代码中知道,在多线程的编程中对共享数据的写入操作,一定要达到原子性。至于如何做到这点,InterlockedAnd和InterlockedOr做了很好的诠释:

While循环的目的就是保证target值以***的值做与操作,如果传入的值在执行的过程被其他线程改变的话,那么是不会退出该循环的,并会利用改变后的值重新做次与操作。

2、理解Enter和Exit

这两个方法很难写出来解释,用图是最清晰的。

.NET开发中多线程的使用

曾经的晕眩:

1、Enter方法中为什么存在循环,为什么不是执行完waitone就结束,必须m_lockState等于c_IsFree的时候才结束?

线程的执行并不完全按照先前排好的顺序去执行,有时会发生一些特殊的情况来使改变线程的调度顺序,所以就可能会出现上图灰色部分的情况,则为了解决该可能发生的问题(概率很小)循环机制就出现了。

2、为什么在WaitOne和Release之前,除了增加和减少等待者外,还需要判断m_lockstate是否改变(进入Enter到执行Waitone前的这段时间)?

一般性的思维:

.NET开发中多线程的使用

该程序的思维:

.NET开发中多线程的使用

这样做的好处就是尽量少的操作内核对象,提高性能!

多线程编程虽然复杂,但是我觉得很有意思和挑战性,而且随着硬件的发展,多线程编程会更加重要,既然已经上路就让我们走到尽头!

到此,相信大家对“.NET开发中多线程的使用”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. 在iOS开发为什么使用多线程 ,多线程有哪些方法。
  2. [.NET开发] winform开发中使用datagridview遇到的问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

上一篇:Ubuntu 9.04 RC的安装过程

下一篇:JAVA里字符编码的原理和使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》