เธรดกับกระบวนการใน Linux


253

ฉันเพิ่งได้ยินบางคนบอกว่าใน Linux มันเกือบจะดีกว่าที่จะใช้กระบวนการแทนเธรดเนื่องจาก Linux มีประสิทธิภาพมากในการจัดการกระบวนการและเนื่องจากมีปัญหามากมาย (เช่นการล็อค) ที่เกี่ยวข้องกับเธรด อย่างไรก็ตามฉันสงสัยเพราะดูเหมือนว่าเธรดอาจให้ประสิทธิภาพที่ดีขึ้นในบางสถานการณ์

ดังนั้นคำถามของฉันคือเมื่อเผชิญกับสถานการณ์ที่เธรดและกระบวนการสามารถจัดการได้ดีฉันควรใช้กระบวนการหรือเธรด ตัวอย่างเช่นถ้าฉันเขียนเว็บเซิร์ฟเวอร์ฉันควรใช้กระบวนการหรือชุดข้อความ (หรือชุดค่าผสม) หรือไม่


มีความแตกต่างกับ Linux 2.4 หรือไม่?
mouviciel

3
ความแตกต่างระหว่างกระบวนการและเธรดภายใต้ Linux 2.4 คือเธรดจะแบ่งส่วนต่าง ๆ ของสถานะ (พื้นที่ที่อยู่การจัดการไฟล์ ฯลฯ ) มากกว่ากระบวนการซึ่งโดยปกติจะไม่ NPTL ภายใต้ Linux 2.6 ทำให้สิ่งนี้ชัดเจนขึ้นเล็กน้อยโดยให้ "กลุ่มเธรด" ซึ่งเป็น "กระบวนการ" ใน win32 และ Solaris
MarkR

6
การเขียนโปรแกรมพร้อมกันเป็นเรื่องยาก ยกเว้นกรณีที่คุณต้องการมากที่มีประสิทธิภาพสูงเป็นสิ่งสำคัญที่สุดในการถ่วงดุลอำนาจของคุณมักจะเป็นความยากลำบากในการแก้จุดบกพร่อง กระบวนการทำเพื่อแก้ปัญหาที่ง่ายกว่ามากในส่วนนี้เนื่องจากการสื่อสารทั้งหมดนั้นชัดเจน (ง่ายต่อการตรวจสอบเพื่อเข้าสู่ระบบ ฯลฯ ) ในทางตรงกันข้ามหน่วยความจำที่แบ่งใช้ของเธรดจะสร้าง gazillions ของตำแหน่งที่เธรดหนึ่งสามารถส่งผลกระทบต่อเธรดอื่นอย่างไม่ถูกต้อง
Lutz Prechelt

1
@ LutzPrechelt - การเขียนโปรแกรมพร้อมกันสามารถเป็นแบบมัลติเธรดเช่นเดียวกับหลายกระบวนการ ฉันไม่เห็นว่าทำไมคุณสมมติว่าการเขียนโปรแกรมพร้อมกันเป็นแบบมัลติเธรดเท่านั้น อาจเป็นเพราะข้อ จำกัด ทางภาษาบางอย่าง แต่โดยทั่วไปอาจเป็นได้ทั้งสองอย่าง
iankit

2
ฉันเชื่อมโยง Lutz เพียง แต่ระบุว่าการเขียนโปรแกรมพร้อมกันนั้นยากที่จะเลือก - กระบวนการหรือเธรด - แต่การเขียนโปรแกรมพร้อมกันโดยใช้กระบวนการทำให้การดีบักง่ายขึ้นในหลาย ๆ กรณี
2692263

คำตอบ:


322

Linux ใช้รูปแบบเธรด 1-1 โดยที่ (ไปยังเคอร์เนล) ไม่มีความแตกต่างระหว่างกระบวนการและเธรด - ทุกอย่างเป็นงานที่รันได้ง่าย * * * *

บน Linux การเรียกระบบcloneโคลนงานโดยมีระดับการแชร์ที่กำหนดค่าได้ซึ่ง ได้แก่ :

  • CLONE_FILES: แชร์ตารางตัวบอกรายละเอียดไฟล์เดียวกัน (แทนที่จะสร้างสำเนา)
  • CLONE_PARENT: อย่าตั้งค่าความสัมพันธ์พาเรนต์ - ลูกระหว่างงานใหม่กับงานเก่า (ไม่เช่นนั้นgetppid()= child's parent getpid())
  • CLONE_VM: แบ่งปันพื้นที่หน่วยความจำเดียวกัน (แทนที่จะสร้างสำเนาCOW )

fork()เรียกclone(ใช้งานร่วมกันอย่างน้อย)และpthread_create()เรียกใช้งานร่วมกันมากที่สุดclone( )**

forkไอเอ็นจีมีค่าใช้จ่ายมากกว่าpthread_createไอเอ็นจีเล็กน้อยเนื่องจากการคัดลอกตารางและสร้างการแมป COW สำหรับหน่วยความจำ แต่นักพัฒนาเคอร์เนลลินุกซ์ได้ลอง (และประสบความสำเร็จ) ในการลดต้นทุนเหล่านั้น

การสลับระหว่างงานหากพวกเขาแชร์พื้นที่หน่วยความจำเดียวกันและตารางต่าง ๆ จะถูกกว่านิดหน่อยถ้าไม่ได้แชร์เพราะข้อมูลอาจถูกโหลดในแคชแล้ว อย่างไรก็ตามการสลับงานยังคงเร็วมากแม้ว่าจะไม่ได้แชร์อะไรเลยนี่เป็นสิ่งอื่นที่นักพัฒนาเคอร์เนล Linux พยายามทำให้มั่นใจ (และประสบความสำเร็จในการทำให้มั่นใจ)

ในความเป็นจริงหากคุณใช้ระบบหลายโปรเซสเซอร์การไม่แชร์อาจเป็นประโยชน์ต่อประสิทธิภาพการทำงาน: หากแต่ละงานใช้โปรเซสเซอร์อื่นการซิงโครไนซ์หน่วยความจำที่ใช้ร่วมกันนั้นมีราคาแพง


* ประยุกต์ CLONE_THREADทำให้การส่งสัญญาณถูกแบ่งใช้ (ซึ่งต้องการCLONE_SIGHANDซึ่งแบ่งใช้ตารางตัวจัดการสัญญาณ)

** แบบง่าย มีอยู่ทั้งในSYS_forkและSYS_clonesyscalls แต่ใน kernel ที่sys_forkและsys_cloneมีทั้งห่อบางมากรอบเดียวฟังก์ชั่นที่ตัวเองเป็นเสื้อคลุมรอบบางdo_fork copy_processใช่คำว่าprocess, threadและtaskมีการใช้ค่อนข้างสลับกันในลินุกซ์ ...


6
ฉันคิดว่าเราหายไป 1 คะแนน หากคุณทำหลายขั้นตอนสำหรับเว็บเซิร์ฟเวอร์คุณต้องเขียนกระบวนการอื่นเพื่อเปิดซ็อกเก็ตและส่ง 'งาน' ไปยังเธรดอื่น เธรดให้กระบวนการเดียวหลายเธรดการออกแบบที่สะอาด ในหลายสถานการณ์ด้ายเป็นเพียงธรรมชาติและในสถานการณ์อื่น ๆ กระบวนการใหม่เป็นธรรมชาติ เมื่อปัญหาอยู่ในพื้นที่สีเทาการแลกเปลี่ยนอื่น ๆ ตามที่อธิบายโดย ephemient จะกลายเป็นสิ่งสำคัญ
Saurabh

26
@Saurabh ไม่จริง คุณสามารถได้อย่างง่ายดายsocket, bind, listen, forkและจากนั้นมีกระบวนการหลายacceptการเชื่อมต่อบนซ็อกเก็ตฟังเหมือนกัน กระบวนการสามารถหยุดการยอมรับถ้ามันไม่ว่างและเคอร์เนลจะกำหนดเส้นทางการเชื่อมต่อขาเข้าไปยังกระบวนการอื่น (ถ้าไม่มีใครฟังอยู่เคอร์เนลจะเข้าคิวหรือวางโดยขึ้นอยู่กับlistenงานในมือ) คุณไม่สามารถควบคุมการกระจายงานได้มากไปกว่านั้น แต่โดยทั่วไปก็ดีพอ!
ephemient

2
@Bloodcount กระบวนการ / เธรดทั้งหมดบน Linux ถูกสร้างโดยกลไกเดียวกันซึ่งโคลนกระบวนการ / เธรดที่มีอยู่ ค่าสถานะที่ส่งผ่านเพื่อclone()กำหนดทรัพยากรที่ใช้ร่วมกัน งานยังสามารถunshare()ใช้ทรัพยากรได้ในเวลาต่อมา
ephemient

4
@KarthikBalaguru ภายในเคอร์เนลนั้นมีtask_structแต่ละภารกิจ นี้มักจะเรียกว่า "กระบวนการ" ตลอดรหัสเคอร์เนล แต่มันสอดคล้องกับแต่ละหัวข้อที่ทำงานได้ ไม่มีprocess_struct; หากกลุ่มtask_structs เชื่อมโยงกันด้วยthread_groupรายการพวกเขาจะเป็น "กระบวนการ" เดียวกันกับ userspace มีนิด ๆ หน่อย ๆ ของการจัดการพิเศษของ "หัวข้อ" s เช่นทุกหัวข้อพี่น้องจะหยุดการทำงานบนส้อมและ exec และมีเพียง "หลัก" ls /procด้ายแสดงขึ้นมาใน /proc/pidแม้ว่าทุกเธรดจะสามารถเข้าถึงได้ผ่านไม่ว่าจะอยู่ใน/procหรือไม่ก็ตาม
ephemient

5
@KarthikBalaguru เคอร์เนลรองรับพฤติกรรมต่อเนื่องระหว่างเธรดและกระบวนการ ตัวอย่างเช่นclone(CLONE_THREAD | CLONE_VM | CLONE_SIGHAND))จะให้ "เธรด" ใหม่ที่ไม่แบ่งปันไดเรกทอรีการทำงานไฟล์หรือล็อคในขณะที่clone(CLONE_FILES | CLONE_FS | CLONE_IO)จะให้กระบวนการ "" แก่คุณ ระบบพื้นฐานสร้างงานโดยการโคลน fork()และpthread_create()เป็นเพียงฟังก์ชั่นห้องสมุดที่เรียกใช้clone()แตกต่างกัน (อย่างที่ฉันเขียนในคำตอบนี้)
ephemient

60

Linux (และ Unix) ให้ตัวเลือกที่สามแก่คุณ

ตัวเลือก 1 - กระบวนการ

สร้างไฟล์ปฏิบัติการแบบสแตนด์อโลนซึ่งจัดการบางส่วน (หรือทุกส่วน) ของแอปพลิเคชันของคุณและเรียกใช้แยกต่างหากสำหรับแต่ละกระบวนการเช่นโปรแกรมรันสำเนาของตัวเองเพื่อมอบหมายงานให้

ตัวเลือก 2 - หัวข้อ

สร้างไฟล์ปฏิบัติการแบบสแตนด์อโลนซึ่งเริ่มต้นด้วยเธรดเดี่ยวและสร้างเธรดเพิ่มเติมเพื่อทำงานบางอย่าง

ตัวเลือก 3 - ทางแยก

มีเฉพาะใน Linux / Unix เท่านั้นซึ่งแตกต่างกันเล็กน้อย กระบวนการแยกเป็นจริงเป็นกระบวนการของตัวเองด้วยพื้นที่ที่อยู่ของตัวเอง - ไม่มีอะไรที่เด็กสามารถทำได้ (ปกติ) เพื่อส่งผลกระทบต่อพื้นที่ที่อยู่ของผู้ปกครองหรือพี่น้อง

อย่างไรก็ตามหน้าหน่วยความจำจะไม่ถูกคัดลอก แต่เป็น copy-on-write ดังนั้นมักจะใช้หน่วยความจำน้อยกว่าที่คุณคิด

พิจารณาโปรแกรมเว็บเซิร์ฟเวอร์ซึ่งประกอบด้วยสองขั้นตอน:

  1. อ่านการกำหนดค่าและข้อมูลรันไทม์
  2. แสดงคำขอหน้าเว็บ

หากคุณใช้เธรดขั้นตอนที่ 1 จะทำครั้งเดียวและทำขั้นตอนที่ 2 ในหลายเธรด หากคุณใช้กระบวนการ "ดั้งเดิม" ขั้นตอนที่ 1 และ 2 จะต้องทำซ้ำสำหรับแต่ละกระบวนการและหน่วยความจำเพื่อจัดเก็บการกำหนดค่าและข้อมูลรันไทม์ที่ทำซ้ำ หากคุณใช้ fork () คุณสามารถทำขั้นตอนที่ 1 ครั้งเดียวจากนั้น fork () โดยปล่อยให้ข้อมูลรันไทม์และการกำหนดค่าในหน่วยความจำไม่ถูกแตะต้องไม่คัดลอก

ดังนั้นจึงมีสามตัวเลือกจริงๆ


7
@Qwertie forking นั้นไม่เจ๋ง แต่ก็มีหลายไลบรารีที่แตกต่างกันไป (ถ้าคุณใช้มันในการปกครอง) มันสร้างพฤติกรรมที่ไม่คาดคิดซึ่งสร้างความสับสนให้กับโปรแกรมเมอร์ที่มีประสบการณ์
MarkR

2
@MarkR คุณสามารถยกตัวอย่างหรือลิงค์ของวิธีการแยกการแบ่งห้องสมุดและสร้างพฤติกรรมที่ไม่คาดคิด?
Ehtesh Choudhury

18
หากกระบวนการแยกโดยใช้การเชื่อมต่อแบบเปิด mysql สิ่งที่ไม่ดีจะเกิดขึ้นเนื่องจากซ็อกเก็ตใช้ร่วมกันระหว่างสองกระบวนการ แม้ว่ากระบวนการเดียวเท่านั้นที่ใช้การเชื่อมต่อกระบวนการอื่นจะหยุดไม่ให้ถูกปิด
MarkR

1
fork () การเรียกระบบถูกระบุโดย POSIX (ซึ่งหมายความว่ามันมีอยู่ในระบบ Unix ใด ๆ ) หากคุณใช้ Linux API พื้นฐานซึ่งเป็นการเรียกระบบ clone () คุณจะมีตัวเลือกเพิ่มเติมใน Linux มากกว่าแค่สามข้อ .
Lie Ryan

2
@MarkR การแชร์ซ็อกเก็ตนั้นมาจากการออกแบบ นอกจากนี้กระบวนการอย่างใดอย่างหนึ่งสามารถปิดซ็อกเก็ตโดยใช้linux.die.net/man/2/shutdownก่อนที่จะเรียก close () บนซ็อกเก็ต
Lelanthran

53

ขึ้นอยู่กับปัจจัยหลายอย่าง กระบวนการหนักกว่าเธรดมากขึ้นและมีต้นทุนเริ่มต้นและปิดที่สูงขึ้น การสื่อสารระหว่างกระบวนการ (IPC) ก็ยากและช้ากว่าการสื่อสารระหว่างกัน

ในทางตรงกันข้ามกระบวนการมีความปลอดภัยและปลอดภัยกว่าเธรดเนื่องจากแต่ละกระบวนการทำงานในพื้นที่ที่อยู่เสมือนของตัวเอง หากกระบวนการหนึ่งล้มเหลวหรือมีบัฟเฟอร์โอเวอร์รันก็จะไม่ส่งผลกระทบต่อกระบวนการอื่น ๆ เลยในขณะที่หากเธรดขัดข้องก็จะลบเธรดอื่นทั้งหมดในกระบวนการและหากเธรดมีบัฟเฟอร์โอเวอร์รันก็จะเปิดขึ้น รูความปลอดภัยในเธรดทั้งหมด

ดังนั้นหากโมดูลของแอปพลิเคชันของคุณสามารถทำงานได้อย่างอิสระโดยส่วนใหญ่จะมีการสื่อสารเพียงเล็กน้อยคุณควรใช้กระบวนการต่างๆ ประสิทธิภาพการทำงานของ IPC นั้นน้อยมากและคุณจะปลอดภัยจากบั๊กและช่องโหว่ด้านความปลอดภัยเล็กน้อย หากคุณต้องการประสิทธิภาพทุกบิตคุณสามารถรับหรือมีข้อมูลที่ใช้ร่วมกันจำนวนมาก (เช่นโครงสร้างข้อมูลที่ซับซ้อน) ไปกับเธรด


9
คำตอบของอดัมจะทำหน้าที่ได้ดีเช่นเดียวกับการบรรยายสรุปผู้บริหาร สำหรับรายละเอียดเพิ่มเติม MarkR และ ephemient ให้คำอธิบายที่ดี คำอธิบายอย่างละเอียดพร้อมตัวอย่างสามารถดูได้ที่cs.cf.ac.uk/Dave/C/node29.htmlแต่ดูเหมือนว่าจะเป็นวันที่สักหน่อยในส่วนต่างๆ
CyberFonic

2
ไซเบอร์โฟนิคนั้นเป็นจริงสำหรับ Windows อย่างที่ ephemient กล่าวภายใต้กระบวนการ Linux นั้นไม่หนัก และภายใต้ Linux กลไกทั้งหมดที่มีอยู่สำหรับการสื่อสารระหว่างเธรด (futex's, memory memory, pipes, IPC) ก็มีให้สำหรับกระบวนการและทำงานด้วยความเร็วเดียวกัน
รัสเซลล์สจวร์ต

IPC นั้นใช้งานได้ยากกว่า แต่จะเกิดอะไรขึ้นถ้ามีคนใช้ "หน่วยความจำที่ใช้ร่วมกัน"?
abhiarora

11

คนอื่น ๆ ได้กล่าวถึงการพิจารณา

บางทีความแตกต่างที่สำคัญคือในกระบวนการ Windows นั้นหนักและแพงเมื่อเทียบกับเธรดและใน Linux ความแตกต่างก็มีขนาดเล็กกว่ามากดังนั้นสมการจึงดุลในจุดที่ต่างกัน


9

กาลครั้งหนึ่งนานมาแล้วมีระบบปฏิบัติการยูนิกซ์และในระบบยูนิกซ์รุ่นเก่านี้มีค่าใช้จ่ายจำนวนมากสำหรับกระบวนการดังนั้นสิ่งที่คนฉลาดบางคนทำคือสร้างเธรดซึ่งจะแบ่งปันพื้นที่ที่อยู่เดียวกันกับกระบวนการหลักและพวกเขาต้องการบริบทที่ลดลง สวิตช์ซึ่งจะทำให้การสลับบริบทมีประสิทธิภาพมากขึ้น

ใน Linux ร่วมสมัย (2.6.x) มีประสิทธิภาพไม่แตกต่างกันมากนักระหว่างการสลับบริบทของกระบวนการเปรียบเทียบกับเธรด (เฉพาะ MMU stuff เท่านั้นที่เพิ่มเติมสำหรับเธรด) มีปัญหาเกี่ยวกับพื้นที่ที่อยู่ที่ใช้ร่วมกันซึ่งหมายความว่าตัวชี้ความผิดพลาดในเธรดอาจทำให้หน่วยความจำของกระบวนการหลักหรือเธรดอื่นเสียหายภายในพื้นที่ที่อยู่เดียวกัน

กระบวนการได้รับการปกป้องโดย MMU ดังนั้นตัวชี้ความผิดพลาดจะทำให้เกิดสัญญาณ 11 และไม่มีความเสียหาย

โดยทั่วไปแล้วฉันจะใช้กระบวนการ (ไม่ค่อยมีบริบทสลับค่าใช้จ่ายใน Linux แต่การป้องกันหน่วยความจำเนื่องจาก MMU) แต่ pthreads ถ้าฉันจะต้องเรียนตารางเวลาแบบเรียลไทม์ซึ่งเป็นถ้วยชาที่แตกต่างกันทั้งหมดเข้าด้วยกัน

ทำไมคุณคิดว่าเธรดมีประสิทธิภาพที่เพิ่มขึ้นอย่างมากใน Linux คุณมีข้อมูลใด ๆ สำหรับสิ่งนี้หรือมันเป็นเพียงตำนานหรือไม่?


1
ใช่ฉันมีข้อมูลบางอย่าง ฉันรันการทดสอบที่สร้างกระบวนการ 100,000 และการทดสอบที่สร้าง 100,000 เธรด รุ่นของเธรดรันเร็วกว่าประมาณ 9 เท่า (17.38 วินาทีสำหรับกระบวนการ 1.93 สำหรับเธรด) ตอนนี้จะทดสอบเฉพาะเวลาสร้าง แต่สำหรับงานระยะสั้นเวลาสร้างอาจเป็นกุญแจ
user17918

4
@ user17918 - เป็นไปได้หรือไม่ที่คุณจะแบ่งปันรหัสที่คุณใช้ในการคำนวณเวลาที่ระบุไว้ข้างต้น ..
codingfreak

หนึ่งที่แตกต่างกันมากกับกระบวนการเคอร์เนลสร้างตารางหน้าสำหรับทุกกระบวนการและ theads ใช้เพียงหนึ่งตารางหน้าดังนั้นฉันคิดว่าเป็นเรื่องปกติที่กระทู้จะเร็วขึ้นแล้วกระบวนการ
c4f4t0r

อีกวิธีที่ง่ายในการดูคือ TCB นั้นเล็กกว่า PCB ค่อนข้างชัดเจนดังนั้นจึงเป็นที่ชัดเจนว่าการสลับบริบทของกระบวนการที่เกี่ยวข้องกับ PCB จะใช้เวลามากกว่าบิตของการสลับเธรด
Karthik Balaguru

5

งานของคุณเป็นอย่างไร

หากพวกเขาสามารถมีชีวิตอยู่อย่างอิสระจากกันใช้กระบวนการ หากพวกเขาพึ่งพาซึ่งกันและกันแล้วใช้หัวข้อ ด้วยวิธีนี้คุณสามารถฆ่าและรีสตาร์ทกระบวนการที่ไม่ดีโดยไม่รบกวนการดำเนินงานอื่น ๆ


4

เพื่อทำให้เรื่องซับซ้อนยิ่งขึ้นมีสิ่งต่าง ๆ เช่นหน่วยเก็บข้อมูลเธรดโลคัลและหน่วยความจำ Unix ที่ใช้ร่วมกัน

หน่วยเก็บเธรดโลคัลอนุญาตให้แต่ละเธรดมีอินสแตนซ์แยกกันของวัตถุส่วนกลาง ครั้งเดียวที่ฉันใช้มันคือเมื่อสร้างสภาพแวดล้อมการจำลองบน linux / windows สำหรับรหัสแอปพลิเคชันที่ทำงานใน RTOS ใน RTOS แต่ละงานเป็นกระบวนการที่มีพื้นที่ที่อยู่ของตัวเองในสภาพแวดล้อมการจำลองแต่ละงานคือเธรด (ที่มีพื้นที่ที่อยู่ที่ใช้ร่วมกัน) ด้วยการใช้ TLS สำหรับสิ่งต่าง ๆ เช่นซิงเกิลตันเราสามารถแยกอินสแตนซ์สำหรับแต่ละเธรดได้เหมือนกับภายใต้สภาพแวดล้อม RTOS 'ของจริง'

หน่วยความจำที่ใช้ร่วมกันสามารถ (เห็นได้ชัด) ให้ประโยชน์ด้านประสิทธิภาพของการมีหลายกระบวนการในการเข้าถึงหน่วยความจำเดียวกัน แต่ด้วยต้นทุน / ความเสี่ยงที่ต้องประสานกระบวนการอย่างเหมาะสม วิธีหนึ่งในการทำเช่นนั้นคือมีกระบวนการหนึ่งสร้างโครงสร้างข้อมูลในหน่วยความจำที่ใช้ร่วมกันแล้วส่งหมายเลขอ้างอิงไปยังโครงสร้างนั้นผ่านทางการสื่อสารระหว่างกระบวนการแบบดั้งเดิม (เช่นไพพ์ที่มีชื่อ)


1
ฉันใช้ที่เก็บข้อมูลแบบโลคัลสำหรับการรวบรวมสถิติบางครั้งครั้งสุดท้ายที่ฉันเขียนโปรแกรมเครือข่ายแบบเธรด: แต่ละเธรดเขียนไปที่เคาน์เตอร์ของตัวเองไม่จำเป็นต้องล็อค แต่ใช่ TLS ไม่ได้ใช้กันอย่างแพร่หลายหรือจำเป็น หน่วยความจำที่ใช้ร่วมกันในทางกลับกัน ... นอกเหนือจากการส่งข้อมูลอย่างมีประสิทธิภาพคุณยังสามารถแบ่งปันเซมาฟอร์ POSIX ระหว่างกระบวนการต่าง ๆ โดยวางไว้ในหน่วยความจำที่ใช้ร่วมกัน มันน่าทึ่งมาก
ephemient

4

ในงานล่าสุดของฉันกับ LINUX สิ่งหนึ่งที่ต้องระวังคือไลบรารี หากคุณใช้เธรดตรวจสอบให้แน่ใจว่าไลบรารีใด ๆ ที่คุณสามารถใช้ข้ามเธรดนั้นปลอดภัยสำหรับเธรด นี่เผาฉันสองสามครั้ง โดยเฉพาะอย่างยิ่ง libxml2 ไม่ปลอดภัยต่อเธรดออกจากกล่อง สามารถคอมไพล์ด้วยเธรดที่ปลอดภัยได้ แต่นั่นไม่ใช่สิ่งที่คุณได้รับจากการติดตั้งความถนัด


3

ฉันต้องเห็นด้วยกับสิ่งที่คุณได้ยิน เมื่อเราเปรียบเทียบกลุ่มของเรา ( xhplและอื่น ๆ ) เราจะได้รับประสิทธิภาพที่ดีขึ้นอย่างมีนัยสำคัญกับกระบวนการผ่านเธรด</anecdote>


3

การตัดสินใจระหว่างเธรด / กระบวนการขึ้นอยู่กับสิ่งที่คุณจะใช้ ข้อดีอย่างหนึ่งของกระบวนการคือมันมี PID และสามารถถูกฆ่าได้โดยไม่ต้องยกเลิกพาเรนต์

สำหรับตัวอย่างโลกแห่งความเป็นจริงของเว็บเซิร์ฟเวอร์ apache 1.3 ใช้เพื่อสนับสนุนกระบวนการหลายอย่างเท่านั้น แต่ใน 2.0 จะเพิ่มสิ่งที่เป็นนามธรรมเพื่อให้คุณสามารถสลับระหว่างทั้งสองได้ ความคิดเห็น ดูเหมือน จะยอมรับว่ากระบวนการมีความแข็งแกร่งมากขึ้น แต่เธรดสามารถให้ประสิทธิภาพที่ดีขึ้นเล็กน้อย (ยกเว้นหน้าต่างที่ประสิทธิภาพสำหรับกระบวนการแย่ลงและคุณต้องการใช้เธรดเท่านั้น)


2

สำหรับกรณีส่วนใหญ่ฉันต้องการกระบวนการมากกว่าเธรด เธรดอาจมีประโยชน์เมื่อคุณมีงานที่ค่อนข้างเล็ก (เวลาที่ใช้ในกระบวนการ >> โดยแต่ละหน่วยงานที่แบ่งออก) และจำเป็นที่จะต้องมีการแชร์หน่วยความจำระหว่างกัน คิดว่าเป็นชุดใหญ่ นอกจากนี้ (offtopic) โปรดทราบว่าหากการใช้งาน CPU ของคุณเท่ากับ 100 เปอร์เซ็นต์หรือใกล้เคียงกับการใช้งานจริงคุณจะไม่ได้รับประโยชน์จากการใช้มัลติเธรดหรือการประมวลผล (ในความเป็นจริงมันจะแย่ลง)


คุณหมายถึงไม่มีประโยชน์อะไร วิธีการเกี่ยวกับการคำนวณหนักในด้าย GUI? การย้ายไปยังเธรดแบบขนานจะดีกว่ามากจากประสบการณ์ผู้ใช้ไม่ว่า CPU จะโหลดอย่างไร
olegst

2

เธรด -> เธรดใช้พื้นที่หน่วยความจำร่วมกันซึ่งเป็นนามธรรมของ CPU มันมีน้ำหนักเบา กระบวนการ -> กระบวนการมีพื้นที่หน่วยความจำของตัวเองมันเป็นนามธรรมของคอมพิวเตอร์ เพื่อให้งานคู่ขนานคุณต้องสร้างซีพียูให้เป็นนามธรรม อย่างไรก็ตามข้อดีของการใช้กระบวนการผ่านเธรดคือความปลอดภัยความเสถียรในขณะที่เธรดใช้หน่วยความจำน้อยกว่ากระบวนการและให้เวลาแฝงที่น้อยลง ตัวอย่างในแง่ของเว็บคือ chrome และ firefox ในกรณีของ Chrome แต่ละแท็บนั้นเป็นกระบวนการใหม่ดังนั้นการใช้หน่วยความจำของ chrome จะสูงกว่า firefox ในขณะที่ความปลอดภัยและเสถียรภาพที่ให้นั้นดีกว่า firefox ความปลอดภัยที่โครเมี่ยมจัดหาให้นั้นดีกว่าเนื่องจากแต่ละแท็บเป็นกระบวนการใหม่แท็บต่าง ๆ ไม่สามารถสอดแนมในพื้นที่หน่วยความจำของกระบวนการที่กำหนดได้


2

ฉันคิดว่าทุกคนทำงานได้ยอดเยี่ยมในการตอบคำถามของคุณ ฉันแค่เพิ่มข้อมูลเพิ่มเติมเกี่ยวกับเธรดและกระบวนการใน Linux เพื่อชี้แจงและสรุปการตอบสนองก่อนหน้านี้บางส่วนในบริบทของเคอร์เนล ดังนั้นการตอบสนองของฉันเกี่ยวกับรหัสเฉพาะเคอร์เนลใน Linux ตามเอกสารของเคอร์เนล Linux ไม่มีความแตกต่างที่ชัดเจนระหว่างเธรดและกระบวนการยกเว้นเธรดใช้พื้นที่ที่อยู่เสมือนที่ใช้ร่วมกันซึ่งแตกต่างจากกระบวนการ โปรดทราบด้วยว่าเคอร์เนล Linux ใช้คำว่า "งาน" เพื่ออ้างถึงกระบวนการและเธรดโดยทั่วไป

"ไม่มีโครงสร้างภายในที่ใช้กระบวนการหรือเธรด แต่มีโครงสร้าง task_struct ที่อธิบายหน่วยการตั้งเวลานามธรรมที่เรียกว่างาน"

นอกจากนี้ตาม Linus Torvalds คุณไม่ควรคิดถึงกระบวนการกับเธรดเลยและเนื่องจากการ จำกัด เกินไปและความแตกต่างเพียงอย่างเดียวคือ COE หรือบริบทของการดำเนินการในแง่ของ "แยกพื้นที่ที่อยู่จากแม่" หรือพื้นที่ที่อยู่ที่ใช้ร่วมกัน ในความเป็นจริงเขาใช้เว็บเซิร์ฟเวอร์เป็นตัวอย่างในการทำให้จุดของเขาที่นี่ (ซึ่งขอแนะนำให้อ่าน)

เครดิตแบบเต็มไปยังเอกสาร kernel ลินุกซ์


-3

หากคุณต้องการแบ่งปันทรัพยากรคุณควรใช้เธรด

พิจารณาข้อเท็จจริงที่ว่าการสลับบริบทระหว่างเธรดนั้นมีราคาถูกกว่าการสลับบริบทระหว่างกระบวนการมาก

ฉันไม่เห็นเหตุผลใดที่จะไปกับกระบวนการที่แยกต่างหากอย่างชัดเจนเว้นแต่คุณจะมีเหตุผลที่ดีที่จะทำเช่นนั้น (ความปลอดภัยการทดสอบประสิทธิภาพที่พิสูจน์แล้ว ฯลฯ ... )


3
ฉันมีตัวแทนในการแก้ไข แต่ฉันไม่ค่อยเห็นด้วย การสลับบริบทระหว่างกระบวนการต่างๆบน Linux นั้นมีราคาถูกเกือบเท่ากับการสลับบริบทระหว่างเธรด
ephemient
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.