【C#学习笔记】C#中的System.Threading

MultiThreading ? ? ?

在说C#中的System.Threading之前,先来简单说说Process, Thread, CPU, 和OS,算是一个铺垫,说的比较浅,都算是OS课的范畴。话说这是我转专业上的第一门课,当时几乎没有任何编程基础和计算机基础知识,可谓相当痛苦。学习效果也比较渣,现在算是回头慢慢补救。

Process 和 Thread 的比较

  • Process(进程)
    Process是正在运行的应用程序的实例(executing instance)。比如我们双击Microsoft Word图标,就启动了一个Process。所以说,一台计算机上可以运行多个Process

  • Thread(线程)

  • 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。

  • 线程是进程中的一个实体,是被系统独立调度和分派的基本单位。

  • 一个进程可以有很多线程,每条线程并行执行不同的任务,称为多线程(multi-threading)。

比如, 你在word中单击打印就开启了一个新的线程(backgroud thread),但同时你可以返回主页面继续进行文字编辑(这是另外一个thread accept user input)。

推荐当年看过的一篇@阮一峰大神的blog,浅显易懂 - 进程与线程的一个简单解释

单核CPU的运行方式

  • 运行一个thread
  • thread首先加载到RAM中
  • 通过bus转移到CPU的pipeline中(一个queue)
  • 指令集(instruction set)中的指令依此被执行
  • 运行多个threads
  • 比如,两个threads加载到RAM中
  • 此时,在CPU和RAM中多了一个scheduler,负责把thread转移到CPU的pipeline中,scheduler会在两个threads之间相互转换,分别给每个thread一定的time slice
  • 对于我们而言,当time slice足够小,看起来两个threads就像是同时多线程(Simultaneous multithreading)

发展

伴随着Multi-task OSMulti-thread Application的出现,CPU设计也开始适应这种需求,出现了:

  • Hyper Threading
  • Multi-Core CPU
  • Multi CPU

C#中的 System.Threading 命名空间

  • 第一个例子,不使用System.Threading
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 第一个控制台程序
namespace LearnThread
{
    class Program
    {
        static void subTask()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("subTask is running");
            }
        }
        static void Main(string[] args)
        {
            subTask();
            for (int i = 0; i < 5; i++ )
            {
                Console.WriteLine("main is running");
            }
            Console.ReadLine();
        }
    }
}

subTask运行结束之后才会运行main中的for循环,运行结果为

subTask is running
subTask is running
subTask is running
subTask is running
subTask is running
main is running
main is running
main is running
main is running
main is running
  • 第二个例子,使用System.Threading,建立一个新thread
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// 第二个控制台程序
namespace LearnThread
{
    class Program
    {
        static void subTask()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("subTask is running");
            }
        }
        static void Main(string[] args)
        {
            // create one thread
            Thread t = new Thread(new ThreadStart(subTask)); 
            // invoke this thread
            t.Start();
            for (int i = 0; i < 5; i++ )
            {
                Console.WriteLine("main is running");
            }
            Console.ReadLine();
        }
    }
}

在运行subTask这个thread的时候,并不是运行到结束再执行main中的for循环,而是交替执行,类似Simultaneous multithreading,运行结果为(结果随机)

subTask is running
main is running
main is running
subTask is running
subTask is running
main is running
subTask is running
subTask is running
main is running
main is running

可见,System.Threading命名空间中的Thread类可以帮助我们实现程序中的并行。

  • System.Threading.Thread类中常见的方法
    Thread.Start(): 启动线程的执行
    Thread.Suspend(): 挂起线程,或者如果线程已挂起,则不起作用;
    Thread.Resume(): 继续已挂起的线程
    Thread.Interrupt(): 中止处于 Wait或者Sleep或者Join 线程状态的线程
    Thread.Join(): 阻塞调用线程,直到某个线程终止时为止
    Thread.Sleep(): 将当前线程阻塞指定的毫秒数
    Thread.Abort(): 终止此线程的过程。如果线程已经在终止,则不能通过Thread.Start()来启动线程

Thread的两种类型

  • Foreground thread
    如果主程序结束了,foreground thread依然存在或者继续运行。正如下面的例子:
namespace LearnThread
{
    class Program
    {
        static void Main(string[] args)
        {
            // A thread will be created to run
            // function1 parallely
            Thread obj1 = new Thread(Function1);
            obj1.IsBackground = true;
            obj1.Start();

            // the control will come here and exit the main function
            Console.WriteLine("The main application has exited");
        }

        static void Function1()
        {
            Console.WriteLine("Function 1 entered");
            // wait here until the user put any input
            Console.ReadLine();
            Console.WriteLine("Function 1 is exited");
        }
    }
}

程序的运行结果为:

The main application has exited
Function 1 entered
hello
Function 1 exited
Press any key to continue . . . 

可见,虽然主程序结束了,foreground thread依然会等待用户输入,在用户输入hello之后,执行最后一句,退出

  • Background thread
    如果主程序结束了,background thread也随即结束。正如下面例子:
namespace LearnThread
{
    class Program
    {
        static void Main(string[] args)
        {
            // A thread will be created to run
            // function1 parallely
            Thread obj1 = new Thread(Function1);
            obj1.IsBackground = true;
            obj1.Start();

            // the control will come here and exit the main function
            Console.WriteLine("The main application has exited");
        }

        static void Function1()
        {
            Console.WriteLine("Function 1 entered");
            // wait here until the user put any input
            Console.ReadLine();
            Console.WriteLine("Function 1 is exited");
        }
    }
}

改程序的输出结果为:

The main application has exited
Function 1 entered
Press any key to continue . . . 

可见,主程序退出后,background thread也结束了,没有再等待用户输入

关于 Thread Safe Object

  • 在两个thread中运行下面的程序,如果我们不考虑thread safe的问题,程序会报错,因为会出现作为除数的情况
Random o = new Random();
for (long i = 0; i < 10000; i++)
{
    Num1 = o.Next(1, 2);
    Num2 = o.Next(1, 2);
    int result = Num1/Num2;
    Num1 = 0;
    Num2 = 0;
}
  • 在.NET中提供的解决方案:

  • Lock

  • Mutex

  • Semaphore

  • 比如,使用lock修改后的程序

Random o = new Random();
for (long i = 0; i < 10000; i++)
{
    lock (this)
    {
        Num1 = o.Next(1, 2);
        Num2 = o.Next(1, 2);
        int result = Num1/Num2;
        Num1 = 0;
        Num2 = 0;
    }
}

更多资源

  1. C# Multithreading Example
  2. Thread Class (MSDN)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容