C# 的线程

第1部分:起步

介绍和概念

c#支持通过多线程并行执行代码。线程是一个独立的执行路径,能够与其他线程同时运行。

一个c#客户端程序(控制台、WPF或Windows窗体)从一个由CLR和操作系统(“主”线程)自动创建的线程开始,并且通过创建额外的线程来实现多线程。下面是一个简单的示例及其输出:

所有的示例都假设导入了以下名称空间:

使用系统;

使用System.Threading;

类ThreadTest

{

静态void Main()

{

线程t = new Thread(WriteY);/ /启动一个新线程

t.Start();/ /运行WriteY()

/ /同时,在主线程上做一些事情。

for(int i = 0;i < 1000;i + +)控制台。写(“x”);

}

静态孔隙WriteY()

{

for(int i = 0;i < 1000;i + +)控制台。写(“y”);

}

}

xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyy

yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxx

xxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

yyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

……

主线程创建一个新的线程t,它运行一个重复打印字符“y”的方法。同时,主线程反复打印字符“x”:

开始一个新的线程

一旦启动,线程的IsAlive属性将返回true,直到线程结束。当传递到线程的构造函数的委托完成执行时,线程结束。一旦结束,线程无法重新启动。

CLR将每个线程分配其自己的内存堆栈,这样本地变量就会保持分离。在下一个示例中,我们定义了一个带有局部变量的方法,然后在主线程和新创建的线程上同时调用方法:

静态void Main()

{

新线程(Go). start();/ /调用Go()在新线程上

Go();/ / Call Go()在主线程上

}

静态空去()

{

/ /声明并使用局部变量—“循环”

for(int cycle = 0;循环< 5;循环+ +)控制台。写(‘ ? ‘);

}

? ? ? ? ? ? ? ? ? ?

每个线程的内存堆栈上都创建了一个单独的循环变量副本,因此可以预见,输出是10个问号。

如果线程共享同一个对象实例的公共引用,则共享数据。例如:

类ThreadTest

{

bool完成;

静态void Main()

{

ThreadTest tt = new ThreadTest();/ /创建一个通用实例

新线程(tt.Go).Start();

tt.Go();

}

/ /注意,Go现在是一个实例方法

空去()

{

如果(完成){ done = true;控制台。WriteLine(“完成”);}

}

}

因为两个线程都在同一个ThreadTest实例上调用Go(),它们共享完成的字段。这样做的结果是“完成”,而不是两次。

完成

静态字段提供了在线程之间共享数据的另一种方法。这里有一个与静态字段相同的例子:

类ThreadTest

{

静态的bool完成;/ /静态字段在所有线程之间共享

静态void Main()

{

新线程(去).Start();

();

}

静态空去()

{

如果(完成){ done = true;控制台。WriteLine(“完成”);}

}

}

这两个例子都说明了另一个关键概念:线程安全(或者更确切地说,是线程安全)。输出实际上是不确定的:有可能(尽管不太可能)“完成”可以打印两次。但是,如果我们在Go方法中交换语句的顺序,“完成”的概率就会急剧增加:

静态空去()

{

如果(!){控制台。WriteLine(“Done”);Done = true;

}

完成

完成(通常是!)

问题是,一个线程可以对if语句进行评估,而另一个线程正在执行WriteLine语句——在它有机会设置为true之前。

补救办法是在阅读和写作时获得一个独占锁。c#为这个目的提供了锁语句:

类为

{

静态弯曲件;

静态readonly对象locker = new object();

静态void Main()

{

新线程(去).Start();

();

}

静态空去()

{

锁(锁)

{

如果(!){控制台。WriteLine(“Done”);Done = true;

}

}

}

当两个线程同时争用一个锁(在本例中是一个锁),一个线程等待,或者阻塞,直到锁可用。在这种情况下,它只确保一个线程可以一次输入关键的代码段,并且“完成”将只打印一次。以这种方式保护的代码—从多线程上下文中的不确定性—称为线程安全。

共享数据是多线程中复杂性和模糊错误的主要原因。虽然通常是必要的,但要尽可能的简单。

线程虽然被阻塞,但不会消耗CPU资源。

加入和睡眠

您可以通过调用它的联接方法等待另一个线程结束。例如:

静态void Main()

{

线程t =新线程

时间: 2024-08-29 14:08:35

C# 的线程的相关文章

各科基础详实

一. Java基础部分 1. JAVA的基本数据类型有哪些 ?  String 是不是基本数据类型 ? 2. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 3. Java有没有goto? 7 4. 说说&和&&的区别. 7 5. 在JAVA中如何跳出当前的多重嵌套循环? 7 6. switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 8 7. short s1 = 1; s1 = s1 + 1;有什么

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new

201709018工作日记--线程状态的转换

先来张图: 线程在一定条件下,状态会发生变化: 1.新建状态(New):新创建了一个线程对象 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权. 3.运行状态(Running):就绪状态的线程获取了CPU,执行程序代码. 4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行.直到线程进入就绪状态,才有机会转到运行状态.阻塞的情况分三种:   (一).等

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

线程的控制和线程池

一.WaitHandle: ”.Net 中提供了一些线程间更自由通讯的工具,他们提供了通过"信号"进行通讯的机制 可以通过ManualResetEvent,AutoResetEvent(他是在开门并且一个 WaitOne 通过后自动关门)来进行线程间的通讯 waitOne:    等待开门 Set:           开门 Reset:       关门 static void Main(string[] args) { ManualResetEvent mre = new Manu

内存池、进程池、线程池

首先介绍一个概念"池化技术 ".池化技术 一言以蔽之就是:提前保存大量的资源,以备不时之需以及重复使用. 池化技术应用广泛,如内存池,线程池,连接池等等.内存池相关的内容,建议看看Apache.Nginx等开源web服务器的内存池实现. 起因:由于在实际应用当中,分配内存.创建进程.线程都会设计到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作.           因此,当程序中需要频繁的进行内存申请释放,进程.线程创建销毁等操作时,通常会使用内存池.进程池.

线程高级

例题,哲学家用餐: 在一张餐桌上坐着五个哲学家,但是却只有五根筷子,每个哲学家只有一根筷子,所以当一个哲学家要夹菜的时候需要用他旁边那个哲学家的筷子,被拿走筷子的哲学家则只能等待那个哲学家吃完放下筷子他才能夹菜. 示意图:  设计思路: 首先编写一个筷子类,每根筷子都是一个对象,这个类里有拿起.放下两个方法:当一个哲学家线程来调用拿起方法时,下一个哲学家线程就要进入等待状态,然后这个哲学家线程调用放下方法后,就激活那个等待中的哲学家线程,以此循环,轮流使用筷子. 代码示例:  接着设计哲学家类,

缓冲池,线程池,连接池

SSH:[email protected]:unbelievableme/object-pool.git   HTTPS:https://github.com/unbelievableme/object-pool.git 缓冲池 设计要点:包含三个队列:空缓冲队列(emq),装满输入数据的输入的队列(inq),装满输出数据的输出队列(outq),输入程序包括收容输入(hin),提取输入(sin),输出程序包括收容输出(hout)和提取输出(sout). 注意点:输入程序和输出程序会对缓冲区并发访

能够在子线程绘画的View SurfaceView

转载请注明出处:王亟亟的大牛之路 近期两天都没有写文章,一方面是自己在看书.一方面不知道写什么,本来昨天想写Glide或者RxAndroid的东西结果公司的"狗屎"网怎么都刷不好Gradle我也是无语了(FQ也没用).准备今天背着笔记本 回家搞.真是服了.. 抱怨的话不说了,来看下这一篇要讲的主角 SurfaceView,关于SurfaceView的文章事实上在别的一些网站上也有,由于我之前没写过,所以也就一直没整这部分的内容(别人写的好坏反正找好的点自己吸收吧,嘿嘿) 问题:Surf

java线程安全问题之静态变量、实例变量、局部变量

Java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如:"一个类在可以被多个线程安全调用时就是线程安全的". 此处不赘述了,首先给出静态变量.实例变量.局部变量在多线程环境下的线程安全问题结论,然后用示例验证,请大家擦亮眼睛,有错必究,否则误人子弟! 静态变量:线程非安全. 静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态