.net多线程引入初探

简介: 一、多线程入的好处     在应用程序中使用多个线程的好处是每个线程都可以异步执行。对于Windows应用程序,耗时的任务可以在后台执行,而使应用程序的窗口和控件保持响应。

一、多线程入的好处

    在应用程序中使用多个线程的好处是每个线程都可以异步执行。对于Windows应用程序,耗时的任务可以在后台执行,而使应用程序的窗口和控件保持响应。对于服务器应用程序,多线程处理提供了用不同线程处理每个传入请求的能力。否则,在完全满足前一个请求之前,将无法处理每个新请求。


二、多线程带来的并发问题

    然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问、即必须确保任何共享数据都处于被保护状态。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。

案例测试代码:


  1. namespace MultiThreadPrint
  2. {
  3.     public class CPrinter
  4.     {
  5.         public void PrintNumbers()
  6.         {
  7.             Console.WriteLine("{0} is excuting PrintNumbers()", Thread.CurrentThread.Name);
  8.             for (int i = 0; i 10; i++)
  9.             {
  10.                 Random r = new Random();
  11.                 Thread.Sleep(1000 * r.Next(5));
  12.                 Console.Write("{0}, ", i);
  13.             }
  14.             Console.WriteLine();
  15.         }
  16.     };
  17.     class Program
  18.     {
  19.         static void Main(string[] args)
  20.         {
  21.             CPrinter p = new CPrinter();
  22.             // Thread threads[] = new Thread[10]; /* Note that this is the wrong way. */
  23.             Thread[] threads = new Thread[10]; // This is create array,not concrete thread.
  24.             for (int i = 0; i 10; i++)
  25.             {
  26.                 threads[i] = new Thread(new ThreadStart(p.PrintNumbers));
  27.                 threads[i].Name = "Worker thread #" + i.ToString();
  28.             }
  29.             foreach (Thread t in threads)
  30.             {
  31.                 t.Start();
  32.             }
  33.             Console.ReadLine();
  34.         }
  35.     }
  36. }


image图1

    由图1可以看出,十个线程共享一个CPrinter对象时,输出的数据并不是“0,1,2,3,4,5,6,7,8,9”这样有规律的输出,而是出现了各个数据的穿插。说明有某一个时间片线程A调用了CPrinter的PrintNumbers(),别一个时间片线程B也调用了CPrinter的PrintNumbers(),很明显线程A的循环并没有完全执行。而CPrinter对象在各个不同线程的相互竞争中所以打印出了这图1的没规律数据。

 

三、实现数据同步的相关方法

    对于整数数据类型简单操作,可以用Interlocked类的成员来实现线程同步。对于其他所有数据类型和非线程安全的资源,需要使用lock\mutex等机制来处理,详情后解。下面给出Interlocked的案例。


  1. namespace InterlockedHandle
  2. {
  3.     class Program
  4.     {
  5.         //0 for false, 1 for true.
  6.         private static int usingResource = 0;
  7.         private static Object currentMso;
  8.         private static Object globalMso = new Object();
  9.         private const int numThreadIterations = 5;
  10.         private const int numThreads = 10;
  11.         static void Main()
  12.         {
  13.             Thread myThread;
  14.             Random rnd = new Random();
  15.             for (int i = 0; i numThreads; i++)
  16.             {
  17.                 myThread = new Thread(new ThreadStart(MyThreadProc));
  18.                 myThread.Name = String.Format("Thread{0}", i + 1);
  19.                 //Wait a random amount of time before starting next thread.
  20.                 Thread.Sleep(rnd.Next(0, 1000));
  21.                 myThread.Start();
  22.             }
  23.             Console.ReadLine();
  24.         }
  25.         private static void MyThreadProc()
  26.         {
  27.             for (int i = 0; i numThreadIterations; i++)
  28.             {
  29.                 UseResource();
  30.                 //Wait 1 second before next attempt.
  31.                 Thread.Sleep(1000);
  32.             }
  33.         }
  34.         //A simple method that denies reentrancy.
  35.         static bool UseResource()
  36.         {
  37.             //0 indicates that the method is not in use.
  38.             if (0 == Interlocked.Exchange(ref usingResource, 1))
  39.             {
  40.                 Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name);
  41.                 //Code to access a resource that is not thread safe would go here.
  42.                 //Simulate some work
  43.                 Thread.Sleep(500);
  44.                 Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name);
  45.                 //Release the lock
  46.                 Interlocked.Exchange(ref usingResource, 0);
  47.                 return true;
  48.             }
  49.             else
  50.             {
  51.                 Console.WriteLine(" {0} was denied the lock", Thread.CurrentThread.Name);
  52.                 return false;
  53.             }
  54.         }
  55.     }
  56. }



image图2

    图2可以看到usingResource 作为一个整型数据类型,当多个线程想对异步其进行访问时,因为这存在数据的同步问题。这里使用了Interlocked来使用每个线程要想访问usingResource,必须等待别一个线程使用完退出后才行!这样保证了数据的安全。

 

参考文献

MSDN--Interlocked 类

《C#与.NET4高级程序设计(第5版)》

相关文章
|
并行计算 安全 Java
C# .NET面试系列四:多线程
<h2>多线程 #### 1. 根据线程安全的相关知识,分析以下代码,当调用 test 方法时 i > 10 时是否会引起死锁? 并简要说明理由。 ```c# public void test(int i) { lock(this) { if (i > 10) { i--; test(i); } } } ``` 在给定的代码中,不会发生死锁。死锁通常是由于两个或多个线程互相等待对方释放锁而无法继续执行的情况。在这个代码中,只有一个线程持有锁,且没有其他线程参与,因此不
789 3
|
11月前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
196 1
|
开发框架 监控 Java
【.NET Core】多线程之线程池(ThreadPool)详解(二)
【.NET Core】多线程之线程池(ThreadPool)详解(二)
286 3
|
SQL 开发框架 Java
【.NET Core】多线程之线程池(ThreadPool)详解(一)
【.NET Core】多线程之线程池(ThreadPool)详解(一)
719 2
|
算法 安全 Java
【.NET Core】 多线程之(Thread)详解
【.NET Core】 多线程之(Thread)详解
205 1
|
C# Windows
.NET一个线程更新另一个线程的UI(两种实现方法及若干简化)
原文:.NET一个线程更新另一个线程的UI(两种实现方法及若干简化) 本片博文接上一篇:.NET多线程执行函数,给出实现一个线程更新另一个线程UI的两种方法。 Winform中的控件是绑定到特定的线程的(一般是主线程),这意味着从另一个线程更新主线程的控件不能直接调用该控件的成员。
1700 0
|
数据采集 Java C++
【.NET 6】多线程的几种打开方式和代码演示
多线程无处不在,平常的开发过程中,应该算是最常用的基础技术之一了。以下通过Thread、ThreadPool、再到Task、Parallel、线程锁、线程取消等方面,一步步进行演示多线程的一些基础操作。欢迎大家围观。如果大佬们有其他关于多线程的拓展,也欢迎在评论区进行留言,大佬们的知识互助,是.net生态发展的重要一环,欢迎大佬们进行留言,帮助更多的人。
372 0
【.NET 6】多线程的几种打开方式和代码演示
|
安全 NoSQL MongoDB
.Net线程同步技术解读
C#开发者(面试者)都会遇到lock(Monitor),Mutex,Semaphore,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别。
.Net线程同步技术解读
|
XML 存储 开发框架
ASP.NET多线程的使用(二)
线程,是操作系统中的术语,是操作系统进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有很多线程,每条线程并行执行不同的任务。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。我们把用来执行用户任务的线程称为工作线程。而线程池,是一种成熟的线程使用模式。
260 0
ASP.NET多线程的使用(二)
|
存储 开发框架 Java
ASP.NET多线程的使用(一)
线程,是操作系统中的术语,是操作系统进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有很多线程,每条线程并行执行不同的任务。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。我们把用来执行用户任务的线程称为工作线程。而线程池,是一种成熟的线程使用模式。
405 0
ASP.NET多线程的使用(一)

热门文章

最新文章