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?
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?
Câu trả lời:
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.
you will get a stack overflow.
Tràn ngăn xếp trên Tràn ngăn xếp!
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 .
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).
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?
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ể.
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.
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.