每个线程都有自己的堆栈,但它们共用一个公共的堆。
众所周知,堆栈是用于本地/方法变量,堆则是用于实例/类变量。
共享堆对线程有何益处?
由于同时运行了多个线程,因此共享内存可能会导致并发修改、相互排除等问题,增加了负担。
在堆中,线程共享哪些内容。
为什么要这样做?为什么不让每个线程都拥有自己的堆?能否提供一个现实世界的例子来说明这一点,即如何利用线程之间的共享内存?
每个线程都有自己的堆栈,但它们共用一个公共的堆。
众所周知,堆栈是用于本地/方法变量,堆则是用于实例/类变量。
共享堆对线程有何益处?
由于同时运行了多个线程,因此共享内存可能会导致并发修改、相互排除等问题,增加了负担。
在堆中,线程共享哪些内容。
为什么要这样做?为什么不让每个线程都拥有自己的堆?能否提供一个现实世界的例子来说明这一点,即如何利用线程之间的共享内存?
当您想要将数据从一个线程传递到另一个线程时,您会做什么?(如果您从未这样做,那么您将编写单独的程序而不是一个多线程程序。)有两种主要方法:
您似乎默认采用的方法是共享内存:除了具有强制为特定线程保留的数据(例如堆栈)之外,所有数据都可供所有线程访问。基本上,有一个共享堆。这提供了速度:任何时候线程更改某些数据,其他线程都可以看到它。(限制:如果线程在不同的处理器上执行,则程序员需要非常努力地正确且高效地使用共享内存。)大多数主要的命令式语言,特别是Java和C#,支持此模型。
也可以每个线程一个堆,再加上一个共享堆。这需要程序员决定将哪些数据放在何处,而这通常与现有的编程语言不太匹配。
双重方法是消息传递:每个线程都有自己的数据空间;当一个线程想要与另一个线程通信时,它需要显式地向另一个线程发送消息,以将数据从发送者的堆复制到接收者的堆。在这种情况下,许多社区更喜欢将线程称为进程。这提供了安全性:由于线程不能随意覆盖其他线程的内存,因此可以避免很多错误。另一个好处是分布:您可以使线程在不更改程序中的任何一行的情况下在单独的机器上运行。您可以为大多数语言找到消息传递库,但集成通常不太好。理解消息传递的良好语言包括Erlang和JoCaml。
实际上,消息传递环境通常在幕后使用共享内存,至少在线程在同一台机器/处理器上运行时是这样。这可以节省大量的时间和内存,因为从一个线程传递消息到另一个线程不需要复制数据。但由于共享内存对程序员不可见,它固有的复杂性仅限于语言/库的实现。
否则它们就会成为进程。 这就是线程的整个概念,共享内存。
进程通常不共享堆空间。虽然有API允许这样做,但默认情况下进程是分离的。
线程共享堆空间。
这就是“实际想法”——使用内存的两种方式——共享和不共享。
clone()
共享任何您喜欢的内容。 - Matt Joiner在许多语言/运行时中,栈被用于保存函数/方法参数和变量等内容。如果线程共享一个栈,那么情况将会变得非常混乱。
void MyFunc(int a) // Stored on the stack
{
int b; // Stored on the stack
}
int globalValue; // stored on the heap
void Foo()
{
int b = globalValue; // Gets the current value of globalValue
globalValue = 10;
}
void Bar() // Stored on the stack
{
int b = globalValue; // Gets the current value of globalValue
globalValue = 20;
}
void main()
{
globalValue = 0;
Foo();
// globalValue is now 10
Bar();
// globalValue is now 20
}
fork()
。 - Matt Joiner