当多个线程运行相同的代码时,CLR如何设法让它们相互超越。 AppDomain管理这些线程并定义不同线程之间的边界,即使它们可能在相同的代码(可能还有数据)上运行吗?如果是这样的话?
TIA
答案 0 :(得分:7)
简单;对于方法变量(不包括捕获的变量,迭代器块等),变量在堆栈上。每个线程都有不同的堆栈。这与单个线程上的递归方法没有什么不同 - 方法变量是每个调用独立且独立的。
对于堆上的对象... 它不会!! 。没有界限;没有保护。如果您没有正确同步等,则会损坏您的数据。
简而言之,这是你的工作。
答案 1 :(得分:2)
这是一个操作系统实现细节。 Windows维护每个线程的处理器上下文。该上下文包含处理器寄存器状态的副本。对你的问题很重要的是EIP,指令指针和ESP,堆栈指针。指令指针跟踪线程执行的机器代码指令。堆栈指针跟踪当前正在执行的方法的激活帧。每个线程都有自己的堆栈。
由于每个线程都有自己的指令指针,因此每个线程都可以独立于其他线程执行自己的代码。拥有自己的堆栈可确保线程不会踩到彼此的局部变量。您的计算机有数百个线程同时运行。他们轮流在可用的CPU核心上执行代码一段时间。这是操作系统的工作,它将处理器状态保存在线程上下文中,无论何时运行一段时间或阻塞,并且是时候让另一个线程转向。恢复该线程只需将状态从已保存的上下文复制回处理器。它会在中断时停止。
一旦线程开始访问所有线程共享的内存,线程就会变得棘手。在.NET程序中,这是存储在垃圾收集堆上的任何内容以及任何静态变量。有一个线程写入这样的内存和其他线程读取相同的内存需要编排。 lock 关键字是执行此操作的主要方法之一。
AppDomain的相关性是每个AppDomain都有自己的垃圾收集堆和'loader heap'(存储静态变量值的地方)。这可以防止线程完全相互踩踏。它完全等同于一个过程,没有相关的操作系统成本。这在Windows上相当高。 AppDomains在自定义CLR主机(如ASP.NET和SQL Server)上非常重要。它们有助于隔离客户端请求,例如,一个用未处理的异常进行轰炸的网页请求也不会破坏所有其他请求的状态。