2009-11-03 4 views
103

지금까지 내가 알고있는 한, 각 스레드는 운영 체제에 의해 스레드가 생성되면 별개의 스택을 얻습니다. 각 스레드가 자체적으로 별개의 힙을 가지고 있는지 궁금합니다.스레드에 별개의 힙이 있습니까?

+1

플랫폼 및 라이브러리는 무엇입니까? – divegeek

+0

예, windows 및 linux, c 라이브러리 – root

+2

니스. 그 근본적인 질문은 계속 +1하십시오. –

답변

110

아니요. 모든 스레드는 공통 힙을 공유합니다.

thread has a private stack은 항목을 빠르게 추가하고 제거 할 수 있습니다. 이렇게하면 스택 기반 메모리가 빠르게 만들어 지지만 무한 재귀 에서처럼 너무 많은 스택 메모리를 사용하면 스택 오버플로가 발생합니다.

모든 스레드가 동일한 힙을 공유하므로 할당 자/할당 취소 자에 대한 액세스가 동기화되어야합니다. allocator contention을 피하기위한 다양한 방법과 라이브러리가 있습니다.

일부 언어에서는 메모리의 개별 풀 또는 개별 스레드를 만들 수 있습니다.이 풀을 단일 스레드에 할당 할 수 있습니다.

+0

이는 런타임에 따라 다릅니다. – divegeek

+5

일반적으로 스레드는 메모리와 같은 리소스를 공유하므로 비 머리말 스레드 구현은 힙을 공유합니다. –

+10

각 스레드가 자체 스택을 가지고있는 * main * 이유는 스레드가 실제로 함수를 호출하는 것과 같은 것을 할 수 있도록하기 위해서입니다 ... – Edmund

1

일반적으로 스레드는 힙 및 기타 리소스를 공유하지만 그렇지 않은 스레드와 유사한 구조가 있습니다. 이러한 스레드 형 구성 중에는 Erlang의 경량 프로세스와 UNIX의 전체 프로세스 (fork() 호출을 통해 생성됨)가 있습니다. 또한 다중 컴퓨터 동시성에 대해 작업 할 수도 있습니다.이 경우 스레드 간 통신 옵션이 상당히 제한됩니다.

+0

포크는 새로운 메모리 위치에 데이터를 복사 한 새로운 프로세스를 만드는 것과 같다고 생각했습니다. –

+2

fork()는 스레드를 사용할 수있는 많은 유스 케이스에서 사용될 수 있습니다. 쓰기 중 복사 (copy-on-write)로 인해 유닉스 시스템에는 상당한 비용 차이가 없다. 일반적인 유스 케이스는 작업자가 나머지 서비스에서 자율 (웹 서버 등)하는 곳입니다. 또 다른 가능성은 stdin/out을 통해 메인 쓰레드/프로그램과 통신하는 것이다. fork()는 유닉스에서 강하다. 반면에 윈도우 같은 다른 플랫폼은 스레딩을 선호한다.주된 이유는 아마도 fork()를 사용하는 것이 훨씬 간단하고 안전하며 Unix는이 단순 철학을 가지고 있기 때문일 것입니다. 스레드에 대한 느린 전환과 함께 예를 들어 apache webserver를 참조하십시오. – ypnos

9

기본적으로 C에는 단일 힙만 있습니다.

즉, 스레드를 인식하는 일부 할당자는 힙을 분할하여 각 스레드가 할당 할 자체 영역을 갖도록합니다. 이것은 힙 스케일을 더 잘 만들어야한다는 아이디어입니다.

이러한 힙의 한 예는 Hoard입니다.

+0

기본적으로 C 및 C++에는 다중 스레드가 없습니다. 2003 C++ 사양은 최소한 가상 시스템 설계의 스레드에 대한 허용을하지 않으므로 C++의 스레드가 구현 정의됩니다. –

+0

다른 스레드가 힙에서 할당 할 영역이 다르더라도 다른 스레드가 할당 한 데이터를 볼 수 있으므로 스레드는 여전히 동일한 힙을 공유합니다. –

+1

업데이트 : C++ 11 이후 스레드는 더 이상 구현이 정의되지 않습니다. – anthropomorphic

3

각 스레드에는 자체 스택과 호출 스택이 있습니다.

각 스레드는 동일한 힙을 공유합니다.

1

일반적으로 모든 스레드는 동일한 주소 공간을 사용하므로 대개 단 하나의 힙을 갖습니다.

그러나 조금 더 복잡 할 수 있습니다. Thread Local Storage (TLS)을 찾고있을 수도 있지만 단일 값만 저장합니다.

Windows 관련 : TLS 공간은 TlsAlloc을 사용하여 할당 및 TlsFree (개요 here)를 사용하여 해제 할 수 있습니다. 다시 말하지만 힙이 아니라 DWORD입니다.

이상하게도 Windows는 프로세스 당 복수 Heaps을 지원합니다. 하나는 TLS에 힙 핸들을 저장할 수 있습니다. 그런 다음 "스레드 로컬 힙"과 같은 것을 갖게됩니다. 그러나 핸들은 다른 스레드에 알려지지 않았으므로 여전히 동일한 주소 공간이므로 포인터를 사용하여 해당 메모리에 액세스 할 수 있습니다.

EDIT : 일부 메모리 할당 자 (특히 FreeBSD의 경우 jemalloc)는 TLS를 사용하여 스레드에 "경기장"을 할당합니다. 이것은 동기화 오버 헤드를 줄임으로써 다중 코어에 대한 할당을 최적화하기 위해 수행됩니다.

+0

> "이상하게도, Windows는 프로세스 당 여러 개의 힙을 지원합니다."라는 말은 전혀 이상하지 않습니다. 할당 유형에 따라 다른 힙을 사용할 수 있으며 융통성이 추가되었습니다. 물론 VirtualAlloc을 사용하여 언제든지 자신 만의 힙을 만들 수 있습니다. –

5

OS에 따라 다름. Windows 및 Unis의 표준 c 런타임은 스레드간에 공유 힙을 사용합니다. 이것은 모든 malloc/free를 잠그는 것을 의미합니다.

예를 들어 Symbian에서는 스레드가 임의의 힙에 할당 된 데이터에 대한 포인터를 공유 할 수 있지만 각 스레드마다 자체 힙이 제공됩니다. 심비안의 디자인은 alloc/free 동안 락킹의 필요성을 제거 할뿐만 아니라 쓰레드 간의 데이터 소유에 대한 명확한 명세를 장려하기 때문에 내 의견으로는 더 좋다. 또한이 경우 스레드가 죽을 때 할당 된 모든 객체가 필요합니다. 즉, 할당 된 객체가 누설 될 수 없습니다. 제약이있는 메모리가있는 휴대 기기에서 사용하는 데 중요한 속성입니다.

Erlang은 "프로세스"가 가비지 수집의 단위로 작동하는 유사한 디자인을 따릅니다. 모든 데이터는 참조 카운팅 된 이진 BLOB를 제외하고 복사를 통해 프로세스간에 통신됩니다 (필자는 생각합니다).

2

"힙"이라고 할 때 정확히 무슨 뜻인지에 달려 있습니다.

모든 스레드가 주소 공간을 공유하므로 힙 할당 객체는 모든 스레드에서 액세스 할 수 있습니다. 기술적으로, 스택은 이러한 의미로도 공유됩니다. 즉, 다른 스레드의 스택에 액세스하지 못하게하는 것은 아무것도 없습니다.

반면에 메모리를 할당하는 데 사용되는 구조체는입니다. 여기서 힙 메모리 할당을위한 모든 부기가 수행됩니다. 이러한 구조는 스레드 간의 경합을 최소화하기 위해 정교하게 구성되어 있으므로 일부 스레드는 힙 구조 (아레나)를 공유 할 수도 있고 일부 스레드는 별개의 영역을 사용할 수도 있습니다.
다음과 같은 세부 사항의 우수한 설명에 대한 스레드를 참조하십시오 : How does malloc work in a multithreaded environment? FreeRTOS 운영 체제에

+0

+1 : 누구도 (콜) 스택이 공유되었다고 말하지 않았습니다. – user2431763

1

, 작업 (쓰레드) 같은 힙을 공유하지만, 그들 각각은 자신의 스택을 가지고있다. 동일한 메모리 풀이 여러 스레드에서 액세스/공유 할 수 있기 때문에 저전력의 낮은 RAM 아키텍처를 처리 할 때 매우 유용합니다. 그러나 이것은 작은 잡기와 함께 제공되므로 개발자는 malloc을 동기화하기위한 메커니즘 자유가 필요하기 때문에 힙 (예 : 세마포 또는 뮤텍스)에 메모리를 할당하거나 해제 할 때 일부 유형의 프로세스 동기화/잠금을 사용해야합니다.

관련 문제