Các chủ đề có một đống riêng biệt không?


114

Theo như tôi biết, mỗi luồng nhận được một ngăn xếp riêng biệt khi luồng được tạo bởi hệ điều hành. Tôi tự hỏi liệu mỗi luồng có một đống phân biệt với chính nó không?


vâng, cửa sổ và Linux, thư viện c

3
Đẹp. +1 tiếp tục đưa ra những câu hỏi cơ bản.

Câu trả lời:


128

Không. Tất cả các chủ đề chia sẻ một đống chung.

Mỗi luồng có một ngăn xếp riêng , nó có thể nhanh chóng thêm và xóa các mục từ đó. Điều này làm cho bộ nhớ dựa trên ngăn xếp nhanh chóng, nhưng nếu bạn sử dụng quá nhiều bộ nhớ ngăn xếp, như xảy ra trong đệ quy vô hạn, bạn sẽ bị tràn ngăn xếp.

Vì tất cả các luồng chia sẻ cùng một heap, nên quyền truy cập vào bộ cấp phát / bộ định vị giao dịch phải được đồng bộ hóa. Có nhiều phương pháp và thư viện khác nhau để tránh sự tranh chấp của người cấp phát .

Một số ngôn ngữ cho phép bạn tạo các nhóm bộ nhớ riêng, hoặc các vùng riêng lẻ mà bạn có thể gán cho một luồng duy nhất.


5
Thông thường, các luồng chia sẻ tài nguyên, chẳng hạn như bộ nhớ, vì vậy bất kỳ triển khai luồng không phải braindead nào cũng sẽ chia sẻ heap.
R. Martinho Fernandes

10
Các chính lý do mỗi thread có stack riêng của mình là để các chủ đề thực sự có thể làm điều gì đó (như gọi một chức năng) ...
Edmund

3
Mỗi luồng có một ngăn xếp riêng biệt, nhưng nó không nhất thiết phải là 'riêng tư'. Các chủ đề khác thường được phép truy cập nó.
zch

you will get a stack overflow.Tràn ngăn xếp trên Tràn ngăn xếp!
John Strood,

2
@crisron Có thể thiết lập một heap riêng biệt cho từng luồng, nhưng nếu bạn làm điều đó thay vì sử dụng heap được chia sẻ mặc định, thì sẽ khó khăn hơn ví dụ như luồng A cấp phát bộ đệm, lấp đầy dữ liệu, chuyển nó đến luồng B và yêu cầu luồng B sử dụng dữ liệu và sau đó giải phóng bộ đệm (vì luồng B không có quyền truy cập vào đống của luồng A, luồng B không thể giải phóng bộ đệm; luồng B tốt nhất có thể làm là chuyển bộ đệm trở lại luồng A một lần nữa và có chủ đề A miễn phí nó).
Jeremy Friesner

9

Theo mặc định, C chỉ có một heap duy nhất.

Điều đó nói rằng, một số trình cấp phát nhận biết được luồng sẽ phân vùng heap để mỗi luồng có khu vực riêng để phân bổ từ đó. Ý tưởng là điều này sẽ làm cho quy mô đống tốt hơn.

Một ví dụ về một đống như vậy là Hoard .


Theo mặc định C và C ++, không có nhiều luồng. Đặc tả c ++ 2003 ít nhất không cho phép các luồng trong thiết kế máy ảo của nó, vì vậy các luồng, trong c ++, được định nghĩa thực thi.
Chris Becke

Ngay cả khi các luồng khác nhau có các khu vực khác nhau để phân bổ từ trên heap, chúng vẫn có thể thấy dữ liệu được phân bổ bởi một luồng khác, vì vậy các luồng vẫn chia sẻ cùng một heap.
Ken Bloom

1
Cập nhật: kể từ C ++ 11 luồng không còn được xác định triển khai nữa.
Michael Dorst

5

Phụ thuộc vào hệ điều hành. Thời gian chạy c tiêu chuẩn trên windows và unices sử dụng một heap được chia sẻ trên các luồng. Điều này có nghĩa là khóa mọi malloc / miễn phí.

Ví dụ, trên Symbian, mỗi luồng đi kèm với heap riêng của nó, mặc dù các luồng có thể chia sẻ con trỏ tới dữ liệu được phân bổ trong bất kỳ heap nào. Theo tôi, thiết kế của Symbian tốt hơn vì nó không chỉ loại bỏ nhu cầu khóa trong khi cấp phát / miễn phí, mà còn khuyến khích đặc tả rõ ràng về quyền sở hữu dữ liệu giữa các luồng. Cũng trong trường hợp đó khi một luồng chết, nó sẽ lấy tất cả các đối tượng mà nó cấp phát cùng với nó - tức là nó không thể làm rò rỉ các đối tượng mà nó đã cấp phát, đây là một thuộc tính quan trọng cần có trong các thiết bị di động có bộ nhớ hạn chế.

Erlang cũng tuân theo một thiết kế tương tự trong đó một "quy trình" hoạt động như một đơn vị thu gom rác. Tất cả dữ liệu được giao tiếp giữa các quy trình bằng cách sao chép, ngoại trừ các đốm màu nhị phân được tính tham chiếu (tôi nghĩ vậy).


3

Mỗi luồng có ngăn xếp và ngăn xếp cuộc gọi riêng.

Mỗi chủ đề chia sẻ cùng một đống.


3

Nó phụ thuộc vào ý bạn chính xác khi nói "đống".

Tất cả các luồng chia sẻ không gian địa chỉ, vì vậy các đối tượng được phân bổ theo heap đều có thể truy cập được từ tất cả các luồng. Về mặt kỹ thuật, các ngăn xếp cũng được chia sẻ theo nghĩa này, tức là không có gì ngăn cản bạn truy cập vào ngăn xếp của luồng khác (mặc dù hầu như không có ý nghĩa gì khi làm như vậy).

Mặt khác, có những cấu trúc heap được sử dụng để cấp phát bộ nhớ. Đó là nơi mà tất cả các sổ sách kế toán để phân bổ bộ nhớ heap được thực hiện. Các cấu trúc này được tổ chức tinh vi để giảm thiểu sự tranh chấp giữa các luồng - vì vậy một số luồng có thể chia sẻ một cấu trúc heap (một đấu trường) và một số có thể sử dụng các đấu trường riêng biệt.
Xem chủ đề sau để có lời giải thích chi tiết tuyệt vời: Malloc hoạt động như thế nào trong môi trường đa luồng?


1

Thông thường, các luồng chia sẻ heap và các tài nguyên khác, tuy nhiên có những cấu trúc giống như luồng thì không. Trong số các cấu trúc giống như luồng này có các quy trình nhẹ của Erlang và các quy trình đầy đủ của UNIX (được tạo bằng lệnh gọi tới fork()). Bạn cũng có thể đang làm việc trên đồng thời nhiều máy, trong trường hợp đó, các tùy chọn giao tiếp giữa các luồng của bạn bị hạn chế hơn đáng kể.


Tôi nghĩ fork giống như việc tạo ra một quy trình mới chỉ sao chép dữ liệu vào một vị trí bộ nhớ mới.
Jason Tholstrup

2
fork () có thể phân phát trong nhiều trường hợp sử dụng, trong đó các luồng cũng có thể được sử dụng. Do copy-on-write, không có sự khác biệt đáng kể về chi phí trên các hệ thống Unix. Trường hợp sử dụng điển hình là nơi nhân viên tự quản (như máy chủ web) với phần còn lại của dịch vụ. Một khả năng khác là giao tiếp thông qua stdin / out với luồng / chương trình chính. fork () mạnh trên Unix, trong khi các nền tảng khác như Windows thích phân luồng hơn. Lý do chính có lẽ là việc sử dụng fork () đơn giản và an toàn hơn nhiều và Unix có triết lý đơn giản này. Xem ví dụ máy chủ web apache, với quá trình chuyển đổi chậm sang các luồng.
ypnos

1

Nói chung, tất cả các luồng sử dụng cùng một không gian địa chỉ và do đó thường chỉ có một heap.

Tuy nhiên, nó có thể phức tạp hơn một chút. Bạn có thể đang tìm kiếm Lưu trữ cục bộ chủ đề (TLS), nhưng nó chỉ lưu trữ các giá trị đơn lẻ.

Dành riêng cho Windows: Không gian TLS có thể được cấp phát bằng TlsAlloc và được giải phóng bằng TlsFree (Tổng quan tại đây ). Một lần nữa, nó không phải là một đống, chỉ là DWORD.

Thật kỳ lạ, Windows hỗ trợ nhiều Heap cho mỗi quá trình. Người ta có thể lưu trữ xử lý của Heap trong TLS. Sau đó, bạn sẽ có một cái gì đó giống như một "Thread-Local Heap". Tuy nhiên, chỉ cần xử lý không được các luồng khác biết, chúng vẫn có thể truy cập bộ nhớ của nó bằng cách sử dụng con trỏ vì nó vẫn ở cùng một không gian địa chỉ.

CHỈNH SỬA : Một số trình cấp phát bộ nhớ (cụ thể là jemalloc trên FreeBSD) sử dụng TLS để gán "đấu trường" cho các luồng. Điều này được thực hiện để tối ưu hóa phân bổ cho nhiều lõi bằng cách giảm chi phí đồng bộ hóa.


> "Thật kỳ lạ, Windows hỗ trợ nhiều Heap cho mỗi quá trình.", Điều đó không lạ chút nào, người ta có thể sử dụng các heap khác nhau cho các kiểu phân bổ khác nhau, chỉ là tăng thêm tính linh hoạt. Tất nhiên, bạn luôn có thể truy cập VirtualAlloc và xây dựng heap của riêng mình theo cách bạn muốn.

1

Trên Hệ điều hành FreeRTOS, các tác vụ (luồng) chia sẻ cùng một đống nhưng mỗi một trong số chúng có ngăn xếp riêng. Điều này rất hữu ích khi xử lý các kiến ​​trúc RAM thấp năng lượng thấp, vì cùng một nhóm bộ nhớ có thể được truy cập / chia sẻ bởi một số luồng, nhưng điều này đi kèm với một lỗi nhỏ, nhà phát triển cần lưu ý rằng một cơ chế để đồng bộ hóa malloc và miễn phí là cần thiết, đó là lý do tại sao cần sử dụng một số kiểu đồng bộ / khóa quy trình khi cấp phát hoặc giải phóng bộ nhớ trên heap, ví dụ như semaphore hoặc mutex.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.