• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >ASP.NET > .net面向对象之多线程(Multithreading)及 多线程高级应用

.net面向对象之多线程(Multithreading)及 多线程高级应用

作者:yubinfeng 字体:[增加 减小] 来源:互联网 时间:2017-05-11

yubinfeng通过本文主要向大家介绍了multithreading,java multithreading,dx11 multithreading,蓝桥杯multithreading,.net面向对象等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

在.net面向对象程序设计阶段在线程资源共享中的线程安全和线程冲突的解决方案;多线程同步,使用线程锁和线程通知实现线程同步,具体内容介绍如下:

1、 ThreadStatic特性

特性:[ThreadStatic]

功能:指定静态字段在不同线程中拥有不同的值

在此之前,我们先看一个多线程的示例:

我们定义一个静态字段:

 static int num = 0;
 然后创建两个线程进行分别累加:

new Thread(() =>
{
 for (int i = 0; i < 1000000; i++)
 ++num;
 Console.WriteLine("来自{0}:{1}", Thread.CurrentThread.Name, num);
})
{ Name = "线程一" }.Start(); 

new Thread(() =>
{
 for (int i = 0; i < 2000000; i++)
 ++num;
 Console.WriteLine("来自{0}:{1}", Thread.CurrentThread.Name, num);
})
{ Name = "线程二" }.Start();

</div>

运行多次结果如下:

    

可以看到,三次的运行结果均不相同,产生这种问题的原因是多线程中同步共享问题导致的,即是多个线程同时共享了一个资源。如何解决上述问题,最简单的方法就是使用静态字段的ThreadStatic特性。

在定义静态字段时,加上[ThreadStatic]特性,如下:

 [ThreadStatic]
static int num = 0;
</div>两个线程不变的情况下,再次运行,结果如下:

 

不论运行多少次,结果都是一样的,当字段被ThreadStatic特性修饰后,它的值在每个线程中都是不同的,即每个线程对static字段都会重新分配内存空间,就当然于一次new操作,这样一来,由于static字段所产生的问题也就没有了。

2. 资源共享

多线程的资源共享,也就是多线程同步(即资源同步),需要注意的是线程同步指的是线程所访问的资源同步,并非是线程本身的同步。

在实际使用多线程的过程中,并非都是各个线程访问不同的资源。

下面看一个线程示例,假如我们并不知道线程要多久完成,我们等待一个固定的时间(假如是500毫秒):

先定义一个静态字段:

 static int result;
创建线程:

Thread myThread = new Thread(() =>
{
 Thread.Sleep(1000);
 result = 100;
});
myThread.Start();
Thread.Sleep(500); 
Console.WriteLine(result);
</div>

运行结果如下:

 

可以看到结果是0,显然不是我们想要的,但往往在线程执行过程中,我们并不知道它要多久完成,能不能在线程完成后有一个通知?

这里有很多笨的方法,比如我们可能会想到使用一个循环来检测线程状态,这些都不是理想的。

.NET为我们提供了一个Join方法,就是线程阻塞,可以解决上述问题,我们使用Stopwatch来记时,

改进线程代码如下:

System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
Thread myThread = new Thread(() =>
{
 Thread.Sleep(1000);
 result = 100;
});
myThread.Start();
Thread.Sleep(500);
myThread.Join();
Console.WriteLine(watch.ElapsedMilliseconds);
Console.WriteLine(result);

</div>

运行结果如下:

 结果和我们想要的是一致的。

3. 线程锁

除了上面示例的方法,对于线程同步,.NET还为我们提供了一个锁机制来解决同步,再次改进上面示例如下:

先定义一个静态字段来存储锁:

static object locker = new object();
这里我们可以先不用考虑这个对象是什么。继续看改进后的线程:

System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
Thread t1 = new Thread(() =>
{
 lock (locker)
 {
 Thread.Sleep(1000);
 result = 100;
 }
});
t1.Start();
Thread.Sleep(100);
lock (locker)
{
 Console.WriteLine("线程耗时:"+watch.ElapsedMilliseconds);
 Console.WriteLine("线程输出:"+result);
}

</div>

运行结果如下:

运行结果和上面示例一样,如果线程处理过程较复杂,可以看到耗时明显减少,这是一种用比阻塞更效率的方式完成线程同步。

4. 线程通知

前面说到了能否在一个线程完成后,通知等待的线程呢,这里.NET为我们提供了一个事件通知的方法来解决这个问题。

4.1 AutoResetEvent 

先定义一个通知对象

 static EventWaitHandle tellMe = new AutoResetEvent(false);
</div>
改进上面的线程如下:

System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
Thread myThread = new Thread(() =>
{
 Thread.Sleep(1000);
 result = 100;
 tellMe.Set();
});
myThread.Start();
tellMe.WaitOne();
Console.WriteLine("线程耗时:" + watch.ElapsedMilliseconds);
Console.WriteLine("线程输出:" + result);

</div>

 运行结果如下:

4.2 ManualResetEvent

和AutoResetEvent 相对的还有一个 ManualResetEvent 手动模式,他们的区别在于,在线程结束后ManualResetEvent 还是可以通行的,除非手动Reset关闭。下面看一个示例:

先定义一个手动通知的对象:

static EventWaitHandle mre = new ManualResetEvent(false);
</div>


创建线程:

System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
Thread myThreadFirst = new Thread(() =>
{
 Thread.Sleep(1000);
 result = 100;
 mre.Set();
}) { Name = "线程一" };
Thread myThreadSecond = new Thread(() =>
{
 mre.WaitOne();
 Console.WriteLine(Thread.CurrentThread.Name + "获取结果:" + result + "("+System.DateTime.Now.ToString()+")");
}) { Name="线程二"};
myThreadFirst.Start();
myThreadSecond.Start();
mre.WaitOne();
Console.WriteLine("线程耗时:" + watch.ElapsedMilliseconds + "(" + System.DateTime.Now.ToString() + ")");
Console.WriteLine("线程输出:" + result + "(" + System.DateTime.Now.ToString() + ")");

</div>

运行结果如下:

4.3. Semaphore

Semaphore也是线程通知的一种,上面的通知模式,在线程开启的数量很多的情况下,使用Reset()关闭时,如果不使用Sleep休眠一下,很有可能导致某些线程没有恢复的情况下,某一线程提前关闭,对于这种很难预测的情况,.NET提供了更高级的通知方式Semaphore,可以保证在超多线程时不会出现上述问题。

先定义一个通知对象的静态字段:

   static Semaphore sem = new Semaphor

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • .net面向对象之多线程(Multithreading)及 多线程高级应用

相关文章

  • 2018-08-20.net Core连接MongoDB数据库的步骤详解
  • 2017-05-11asp.net Md5的用法小结
  • 2017-05-11ASP.NET将文件写到另一服务器(图文教程)及注意事项
  • 2017-05-11vs2008 安装失败的总结与分享
  • 2017-05-11Asp.net开发常用的51个非常实用的代码
  • 2017-05-11ASP.NET 页面刷新的实现方法(包括html,js)
  • 2018-08-20.NET Core系列之MemoryCache 缓存过期
  • 2017-05-11ASP.NET2.0:页面中链入的CSS、js文件带中文时需注意
  • 2017-05-11asp.net Reporting Service在Web Application中的应用
  • 2017-05-11ashx文件的使用小结

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • asp.net中生成饼状与柱状图实例
    • asp.net下URL网址重写成.html格式、RSS、OPML的知识总结
    • implicitly convert type 'int' to 'short'的原因与解决方法
    • php使用socket编程示例
    • ASP.NET中实现弹出日历示例
    • asp.net XMLHttpRequest实现用户注册前的验证
    • C#调用动态unlha32.dll解压Lha后缀的打包文件分享
    • Asp.net的GridView控件实现单元格可编辑方便用户使用
    • C#处理Json的另外一种方式成功实践
    • ASP.NET 2.0中的数据操作之七:使用DropDownList过滤的主/从报表

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有