26

线程的上下文是否指线程的个人记忆?如果是这样,多个线程之间如何共享内存?

我不是在寻找代码示例——我从高层次上理解同步,我只是对这个术语感到困惑,并希望对幕后实际发生的事情有所了解。

我认为/认为每个线程都有某种私有内存的原因是因为 Java 和 .NET 中的 volatile 关键字,以及如果不使用相同的原语,不同的线程如何具有不同的值。这对我来说总是隐含着私人记忆。

由于我没有意识到这个术语更笼统,我想我是在问上下文切换在 Java 和 C# 中是如何工作的。

4

2 回答 2

42

我认为/认为每个线程都有某种私有内存的原因是因为 Java 和 .NET 中的 volatile 关键字,以及如果不使用相同的原语,不同的线程如何具有不同的值。这对我来说总是隐含着私人记忆。

好的,现在我们正在了解您的困惑的根源。这是现代编程中最令人困惑的部分之一。你必须绕开这个矛盾:

  • 一个进程中的所有线程共享相同的虚拟内存地址空间,但
  • 任何两个线程都可以随时对该空间的内容产生分歧

这个怎么可能?因为

  • 处理器出于性能原因制作内存页面的本地副本,并且很少比较笔记以确保它们的所有副本都说同样的事情。如果两个线程在两个不同的处理器上,那么它们对“相同”内存的看法可能完全不一致。

  • 单线程场景中的内存通常被认为是“静止的”,除非有什么东西导致它发生变化。 这种直觉在多线程进程中为您服务很差。如果有多个线程访问内存,您最好将所有内存视为始终处于不断变化的状态,除非有什么东西迫使它保持静止。一旦您开始认为所有内存都在不断变化,那么很明显两个线程可能具有不一致的视图。即使是同一场风暴,也没有两部风暴期间的海洋电影是相同的。

  • 编译器可以自由地对在单线程系统上不可见的代码进行任何优化。在多线程系统上,这些优化可能会突然变得可见,这可能导致数据视图不一致。

如果其中任何一个不清楚,请先阅读我的文章,解释 C# 中“易失性”的含义:

http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx

然后在此处阅读 Vance 文章中的“内存模型的需要”部分:

http://msdn.microsoft.com/en-us/magazine/cc163715.aspx

现在,关于线程是否有自己的内存块的具体问题,答案是肯定的,有两种方式。首先,由于线程是一个控制点,并且由于堆栈是控制流的具体化,因此每个线程都有自己的百万字节堆栈。这就是线程如此昂贵的原因。在 .NET 中,每次创建线程时,这百万字节实际上都会提交给页面文件,因此请小心创建不必要的线程。

其次,线程具有恰当地命名为“线程本地存储”,它是与每个线程相关联的一小部分内存,线程可以使用它来存储有趣的信息。在 C# 中,您使用ThreadStatic属性将字段标记为线程本地的。

于 2013-08-01T23:06:21.573 回答
12

“线程上下文”的实际组成是特定于实现的,但通常我一直理解线程的上下文是指线程的当前状态以及它在特定时间如何查看内存。这就是“上下文切换”。保存和恢复线程的状态(它是上下文)。

内存在上下文之间共享。它们是同一过程的一部分。

我不认为自己是该主题的专家……但这就是我一直理解该特定术语的含义。

于 2013-08-01T22:38:01.503 回答