เท่าที่ฉันรู้ว่าแต่ละเธรดได้รับสแต็กที่แตกต่างกันเมื่อเธรดถูกสร้างขึ้นโดยระบบปฏิบัติการ ฉันสงสัยว่าแต่ละเธรดมีฮีปที่แตกต่างกันหรือไม่?
เท่าที่ฉันรู้ว่าแต่ละเธรดได้รับสแต็กที่แตกต่างกันเมื่อเธรดถูกสร้างขึ้นโดยระบบปฏิบัติการ ฉันสงสัยว่าแต่ละเธรดมีฮีปที่แตกต่างกันหรือไม่?
คำตอบ:
ไม่เธรดทั้งหมดใช้ฮีปร่วมกัน
แต่ละเธรดมีสแต็กส่วนตัวซึ่งสามารถเพิ่มและลบรายการได้อย่างรวดเร็ว สิ่งนี้ทำให้หน่วยความจำแบบสแต็กทำงานได้รวดเร็ว แต่ถ้าคุณใช้หน่วยความจำสแต็กมากเกินไปเช่นเดียวกับที่เกิดขึ้นในการเรียกซ้ำแบบไม่สิ้นสุดคุณจะได้รับสแตกล้น
เนื่องจากเธรดทั้งหมดใช้ฮีปเดียวกันจึงต้องซิงโครไนซ์การเข้าถึงตัวจัดสรร / deallocator มีวิธีการต่างๆและห้องสมุดเพื่อหลีกเลี่ยงการมีการต่อสู้จัดสรร
บางภาษาอนุญาตให้คุณสร้างพูลหน่วยความจำส่วนตัวหรือแต่ละฮีปซึ่งคุณสามารถกำหนดให้กับเธรดเดียวได้
you will get a stack overflow.
กองซ้อนบน Stack Overflow!
โดยค่าเริ่มต้น C จะมีฮีปเดียวเท่านั้น
ที่กล่าวว่าตัวจัดสรรบางตัวที่ทราบเธรดจะแบ่งพาร์ติชันฮีปเพื่อให้แต่ละเธรดมีพื้นที่ของตัวเองที่จะจัดสรรจาก แนวคิดก็คือสิ่งนี้ควรทำให้ขนาดฮีปดีขึ้น
ขึ้นอยู่กับระบบปฏิบัติการ รันไทม์ c มาตรฐานบน windows และ unices ใช้ฮีปที่แบ่งใช้ข้ามเธรด ซึ่งหมายถึงการล็อคทุก malloc / ฟรี
ตัวอย่างเช่นบน Symbian แต่ละเธรดจะมาพร้อมกับฮีปของตัวเองแม้ว่าเธรดสามารถแชร์พอยน์เตอร์ไปยังข้อมูลที่จัดสรรในฮีปใดก็ได้ การออกแบบของ Symbian นั้นดีกว่าในความคิดของฉันเนื่องจากไม่เพียง แต่ช่วยลดความจำเป็นในการล็อกระหว่างการจัดสรร / ว่าง แต่ยังสนับสนุนข้อกำหนดที่ชัดเจนของการเป็นเจ้าของข้อมูลระหว่างเธรด นอกจากนี้ในกรณีนั้นเมื่อเธรดตายมันจะนำอ็อบเจ็กต์ทั้งหมดที่จัดสรรไปพร้อมกับมันกล่าวคือไม่สามารถรั่วไหลอ็อบเจ็กต์ที่ได้จัดสรรไว้ซึ่งเป็นคุณสมบัติสำคัญที่ต้องมีในอุปกรณ์พกพาที่มีหน่วยความจำ จำกัด
Erlang ยังทำตามการออกแบบที่คล้ายกันโดยที่ "กระบวนการ" ทำหน้าที่เป็นหน่วยเก็บขยะ ข้อมูลทั้งหมดได้รับการสื่อสารระหว่างกระบวนการโดยการคัดลอกยกเว้น binary blobs ที่นับการอ้างอิง (ฉันคิดว่า)
แต่ละเธรดมีสแต็กและโทรสแต็กของตัวเอง
แต่ละเธรดแชร์ฮีปเดียวกัน
ขึ้นอยู่กับว่าคุณหมายถึงอะไรเมื่อพูดว่า "heap"
เธรดทั้งหมดใช้พื้นที่แอดเดรสร่วมกันดังนั้นอ็อบเจ็กต์ที่จัดสรรฮีปจึงสามารถเข้าถึงได้จากเธรดทั้งหมด ในทางเทคนิคแล้วสแต็กจะถูกแชร์เช่นกันในแง่นี้กล่าวคือไม่มีสิ่งใดป้องกันไม่ให้คุณเข้าถึงสแต็กของเธรดอื่น (แม้ว่ามันจะแทบไม่สมเหตุสมผลเลยก็ตาม)
ในทางกลับกันมีโครงสร้างฮีปที่ใช้ในการจัดสรรหน่วยความจำ นั่นคือจุดที่การทำบัญชีทั้งหมดสำหรับการจัดสรรหน่วยความจำฮีปเสร็จสิ้น โครงสร้างเหล่านี้ได้รับการจัดระเบียบอย่างซับซ้อนเพื่อลดความขัดแย้งระหว่างเธรด - ดังนั้นเธรดบางเธรดอาจใช้โครงสร้างฮีปร่วมกัน (อารีน่า) และบางเธรดอาจใช้อารีนาที่แตกต่างกัน
ดูหัวข้อต่อไปนี้สำหรับคำอธิบายที่ยอดเยี่ยมเกี่ยวกับรายละเอียด: malloc ทำงานอย่างไรในสภาพแวดล้อมแบบมัลติเธรด
โดยทั่วไปเธรดจะแชร์ฮีปและทรัพยากรอื่น ๆ อย่างไรก็ตามมีโครงสร้างแบบเธรดที่ไม่มี ในบรรดาโครงสร้างที่มีลักษณะคล้ายเธรดเหล่านี้เป็นกระบวนการที่มีน้ำหนักเบาของ Erlang และกระบวนการแบบเต็มรูปแบบของ UNIX (สร้างขึ้นด้วยการเรียกร้องให้fork()
) นอกจากนี้คุณอาจกำลังทำงานกับการทำงานพร้อมกันหลายเครื่องซึ่งในกรณีนี้ตัวเลือกการสื่อสารระหว่างเธรดของคุณมีข้อ จำกัด มากกว่ามาก
โดยทั่วไปแล้วเธรดทั้งหมดจะใช้พื้นที่แอดเดรสเดียวกันดังนั้นจึงมักจะมีฮีปเดียว
อย่างไรก็ตามอาจซับซ้อนกว่าเล็กน้อย คุณอาจกำลังมองหาThread Local Storage (TLS) แต่จะเก็บค่าเดียวเท่านั้น
เฉพาะ Windows: สามารถจัดสรรพื้นที่ TLS โดยใช้TlsAllocและปล่อยให้เป็นอิสระโดยใช้TlsFree (ภาพรวมที่นี่ ) อีกครั้งมันไม่ใช่กองเป็นเพียง DWORD
น่าแปลกที่ Windows รองรับหลายHeapsต่อกระบวนการ หนึ่งสามารถจัดเก็บที่จับของ Heap ใน TLS จากนั้นคุณจะมีบางอย่างเช่น "Thread-Local Heap" อย่างไรก็ตามเธรดอื่น ๆ ไม่รู้จักแค่ที่จับ แต่ยังสามารถเข้าถึงหน่วยความจำได้โดยใช้พอยน์เตอร์เนื่องจากยังคงเป็นพื้นที่แอดเดรสเดียวกัน
แก้ไข : ตัวจัดสรรหน่วยความจำบางตัว (โดยเฉพาะjemallocบน FreeBSD) ใช้ TLS เพื่อกำหนด "arenas" ให้กับเธรด สิ่งนี้ทำเพื่อเพิ่มประสิทธิภาพการจัดสรรสำหรับหลายคอร์โดยลดค่าใช้จ่ายในการซิงโครไนซ์
บนระบบปฏิบัติการ FreeRTOS งาน (เธรด) จะแบ่งใช้ฮีปเดียวกัน แต่แต่ละงานมีสแตกของตัวเอง สิ่งนี้มีประโยชน์มากเมื่อจัดการกับสถาปัตยกรรม RAM ที่ใช้พลังงานต่ำต่ำเนื่องจากกลุ่มหน่วยความจำเดียวกันสามารถเข้าถึง / แชร์โดยหลายเธรดได้ แต่สิ่งนี้มาพร้อมกับการจับขนาดเล็กผู้พัฒนาต้องจำไว้ว่ากลไกในการซิงโครไนซ์ malloc และจำเป็นต้องใช้ฟรีนั่นคือเหตุผลว่าทำไมจึงจำเป็นต้องใช้การซิงโครไนซ์ / ล็อคกระบวนการบางประเภทเมื่อจัดสรรหรือเพิ่มหน่วยความจำบนฮีปตัวอย่างเช่นเซมาฟอร์หรือมิวเท็กซ์