1. แนวคิดของกระบวนการและเธรด
(1) ในระบบปฏิบัติการแบบดั้งเดิมโปรแกรมไม่สามารถทำงานได้อย่างอิสระและเป็นหน่วยพื้นฐานของการจัดสรรทรัพยากรและการดำเนินงานอิสระเป็นกระบวนการทั้งหมด
ในระบบที่ไม่มีระบบปฏิบัติการวิธีการดำเนินการของโปรแกรมคือการดำเนินการตามลำดับนั่นคือโปรแกรมหนึ่งต้องดำเนินการก่อนที่โปรแกรมอื่นจะสามารถดำเนินการได้ ในสภาพแวดล้อมแบบหลายโปรแกรมได้รับอนุญาตให้ดำเนินการหลายโปรแกรมพร้อมกัน มีความแตกต่างอย่างมีนัยสำคัญระหว่างการดำเนินการสองวิธีของโปรแกรม มันเป็นลักษณะเฉพาะของการดำเนินการพร้อมกันของโปรแกรมที่นำไปสู่การแนะนำแนวคิดของกระบวนการในระบบปฏิบัติการ
เนื่องจากผู้คนเสนอแนวคิดของกระบวนการในปี 1960 กระบวนการจึงถูกใช้ในระบบปฏิบัติการเป็นหน่วยพื้นฐานที่สามารถมีทรัพยากรและทำงานได้อย่างอิสระ จนกระทั่งกลางทศวรรษ 1980 ผู้คนเสนอหน่วยพื้นฐานที่สามารถทำงานได้อย่างอิสระเธรดซึ่งมีขนาดเล็กกว่ากระบวนการเพื่อพยายามใช้เพื่อเพิ่มระดับของการดำเนินการพร้อมกันของโปรแกรมภายในระบบจึงเพิ่มปริมาณงานของระบบ โดยเฉพาะอย่างยิ่งหลังจากเข้าสู่ปี 1990 ระบบหลายโปรเซสเซอร์ได้พัฒนาอย่างรวดเร็ว เธรดสามารถปรับปรุงการดำเนินการแบบขนานของโปรแกรมได้ดีกว่ากระบวนการและออกแรงอย่างเต็มที่ของข้อดีของโปรเซสเซอร์แบบหลายโปรเซสเซอร์ ดังนั้นเธรดได้รับการแนะนำในระบบปฏิบัติการหลายโปรเซสเซอร์ที่เปิดตัวในช่วงไม่กี่ปีที่ผ่านมาเพื่อปรับปรุงประสิทธิภาพของระบบปฏิบัติการ
- ข้อความข้างต้นเป็นข้อความที่ตัดตอนมาจาก "ระบบปฏิบัติการคอมพิวเตอร์ - แก้ไขโดย Tang Xiaodan และอื่น ๆ - Edition 3" (ที่อยู่ดาวน์โหลด)
(2) ตัวเลขต่อไปนี้เป็นคำอธิบายจากผู้ใช้ Zhihu:
ผ่านความเข้าใจทั่วไปข้างต้นเรารู้ว่าเธรดและกระบวนการทำอะไร ดังนั้นขอสรุปแนวคิดสำหรับกระบวนการและเธรดด้านล่าง:
(3) กระบวนการเป็นกิจกรรมที่ใช้งานของโปรแกรมในคอมพิวเตอร์เกี่ยวกับชุดข้อมูลบางอย่างมันเป็นหน่วยพื้นฐานของการจัดสรรทรัพยากรและการกำหนดเวลาของระบบและเป็นพื้นฐานของโครงสร้างระบบปฏิบัติการ ในโครงสร้างคอมพิวเตอร์ที่มุ่งเน้นกระบวนการเริ่มต้นกระบวนการเป็นหน่วยงานการดำเนินการขั้นพื้นฐานของโปรแกรม ในโครงสร้างคอมพิวเตอร์ที่เน้นด้ายร่วมสมัยกระบวนการเป็นภาชนะบรรจุของเธรด โปรแกรมคือคำอธิบายของคำแนะนำข้อมูลและรูปแบบองค์กรและกระบวนการเป็นเอนทิตีของโปรแกรม
(4) เธรดบางครั้งเรียกว่ากระบวนการที่มีน้ำหนักเบา (LWP) เป็นหน่วยที่เล็กที่สุดของการไหลของโปรแกรม เธรดเป็นกระบวนการควบคุมแบบต่อเนื่องเดียวในโปรแกรม หน่วยดำเนินการที่ค่อนข้างอิสระและกำหนดเวลาในกระบวนการเป็นหน่วยพื้นฐานของการกำหนดเวลาอิสระและการส่งซีพียูในระบบซึ่งหมายถึงหน่วยการจัดตารางเวลาของโปรแกรมที่รัน การรันหลายเธรดพร้อมกันในโปรแกรมเดียวเพื่อทำงานที่แตกต่างกันให้เสร็จสมบูรณ์เรียกว่า MultithReading
(5) ความสัมพันธ์ระหว่างกระบวนการและเธรด:
2. Java ใช้วิธีการหลายเธรด
(1) สืบทอดเธรดและเขียนวิธีการเรียกใช้ () ใหม่
คลาสสาธารณะ MyThread ขยายเธรด {@Override โมฆะสาธารณะ Run () {ในขณะที่ (จริง) {System.out.println (this.currentthread (). getName ()); }} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {เธรด MYTHREAD = ใหม่ MYTHREAD (); thread.start (); // วิธีที่ถูกต้องในการเริ่มเธรด}}ผลลัพธ์ผลลัพธ์:
เธรด -0Thread-0Thread-0 ...
นอกจากนี้คุณต้องเข้าใจว่าวิธีการเริ่มต้น () เป็นวิธีการเริ่มต้น () แทนวิธีการเรียกใช้ () หากใช้วิธีการเรียกใช้ () มันเป็นวิธีธรรมดาในการดำเนินการ
(2) ใช้อินเทอร์เฟซที่เรียกใช้งานได้
คลาสสาธารณะ Myrunnable Enprement Runnable {@Override Public Public Void Run () {System.out.println ("123"); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {myrunnable myrunnable = new myrunnable (); เธรดเธรด = เธรดใหม่ (myrunnable, "t1"); thread.start (); -3. ความปลอดภัยของด้าย
แนวคิดเรื่องความปลอดภัยของเธรด: เมื่อหลายเธรดเข้าถึงคลาสที่แน่นอน (วัตถุหรือวิธีการ) คลาสสามารถแสดงพฤติกรรมที่ถูกต้องได้เสมอจากนั้นคลาสนี้ (วัตถุหรือวิธีการ) คือเธรดที่ปลอดภัย
ความปลอดภัยของเธรดคือเมื่อเข้าถึงมัลติเธรดกลไกการล็อคจะถูกนำมาใช้ เมื่อเธรดเข้าถึงข้อมูลบางอย่างของคลาสจะได้รับการปกป้อง เธรดอื่นไม่สามารถเข้าถึงได้จนกว่าเธรดจะอ่านเสร็จแล้วและเธรดอื่น ๆ ไม่สามารถใช้งานได้ จะไม่มีความไม่สอดคล้องกันของข้อมูลหรือมลพิษข้อมูล เธรดไม่ปลอดภัยซึ่งหมายความว่าพวกเขาไม่ได้ให้การป้องกันการเข้าถึงข้อมูล เป็นไปได้ว่าหลายเธรดอาจเปลี่ยนข้อมูลหนึ่งหลังจากอื่นซึ่งส่งผลให้ข้อมูลผลลัพธ์สกปรก กลไกการล็อคทั่วไปที่นี่คือ: ซิงโครไนซ์
4. ตัวดัดแปลงแบบซิงโครไนซ์
(1) ซิงโครไนซ์: คุณสามารถเพิ่มล็อคลงในวัตถุและวิธีการใด ๆ และรหัสล็อคเรียกว่า "พื้นที่ mutex" หรือ "พื้นที่วิกฤต"
(2) ** อย่าใช้อินสแตนซ์ที่ซิงโครไนซ์ ** (รหัส A):
คลาสสาธารณะ MyThread ขยายเธรด {count int ส่วนตัว = 5; @Override โมฆะสาธารณะเรียกใช้ () {count-; system.out.println (this.currentThread (). getName () + "นับ:" + count); เธรด (MyThread, "Thread2"); Thread3 = Thread New Thread (MyThread, "Thread3"); Thread4 = Thread ใหม่ (Mythread, "Thread4"); Thread5 = Thread ใหม่ (Mythread, "Thread5"); thread1.start (); thread2.start ();ผลลัพธ์หนึ่งของผลลัพธ์มีดังนี้:
Thread3 Count: 2Thread4 Count: 1THREAD1 COUNT: 2THREAD2 COUNT: 3THREAD5 COUNT: 0
จะเห็นได้ว่าผลลัพธ์ข้างต้นไม่ถูกต้องเนื่องจากหลายเธรดทำงานวิธีการเรียกใช้ () ในเวลาเดียวกันและแก้ไขการนับซึ่งจะทำให้เกิดข้อผิดพลาด
(3) ** ใช้อินสแตนซ์ที่ซิงโครไนซ์ (รหัส B)::
ชั้นเรียนสาธารณะ MyThread ขยายเธรด {จำนวน int ส่วนตัว = 5; @Override เป็นโมฆะที่ซิงโครไนซ์สาธารณะ Run () {count-; System.out.println (this.currentthread (). getName () + "นับ:" + นับ); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {MyThread mythread = new mythread (); เธรดเธรด 1 = เธรดใหม่ (MyThread, "Thread1"); เธรดเธรด 2 = เธรดใหม่ (MyThread, "Thread2"); เธรดเธรด 3 = เธรดใหม่ (MyThread, "Thread3"); Thread Thread4 = เธรดใหม่ (MyThread, "Thread4"); เธรด Thread5 = เธรดใหม่ (MyThread, "Thread5"); Thread1.start (); Thread2.start (); Thread3.start (); Thread4.start (); Thread5.Start (); -ผลลัพธ์ผลลัพธ์:
Thread1 Count: 4Thread2 Count: 3THREAD3 COUNT: 2THREAD5 COUNT: 1THREAD4 COUNT: 0
จะเห็นได้ว่าความแตกต่างระหว่างรหัส A และรหัส B คือการปรับเปลี่ยนการซิงโครไนซ์จะถูกเพิ่มลงในวิธีการเรียกใช้ ()
คำอธิบายมีดังนี้:
เมื่อหลายเธรดเข้าถึงวิธีการเรียกใช้ MyThread หากใช้การปรับเปลี่ยนซิงโครไนซ์หลายเธรดจะถูกประมวลผลในคิว (คิวที่นี่จะถูกกำหนดตามลำดับของการจัดสรร CPU) หากเธรดต้องการเรียกใช้รหัสในวิธีการปรับเปลี่ยนแบบซิงโครไนซ์ก่อนอื่นจะพยายามรับการล็อค หากได้รับการล็อคให้ดำเนินการเนื้อหาของรหัสรหัสที่ซิงโครไนซ์ หากไม่สามารถล็อคได้เธรดจะพยายามรับการล็อคต่อไปจนกว่าจะได้รับ ยิ่งไปกว่านั้นหลายเธรดจะแข่งขันกันเพื่อล็อคในเวลาเดียวกันซึ่งหมายความว่าการแข่งขันล็อคจะเกิดขึ้น
5. วัตถุมีล็อค! หลายเธรดและล็อคหลายตัว!
อะไรคือวัตถุหนึ่งชิ้นมีหนึ่งล็อคหลายเธรดมีล็อคหลายตัว! ก่อนอื่นมาดูรหัสตัวอย่างด้านล่าง (รหัส C):
คลาสสาธารณะ multithread {private int num = 200; Void PrintNum ที่ซิงโครไนซ์สาธารณะ (String ThreadName, String Tag) {if (tag.equals ("A")) {num = num - 100; System.out.println (threadname + "แท็ก a ตั้งค่า num over!"); } else {num = num - 200; System.out.println (threadname + "tag" + tag + ", num =" + num); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น InterruptedException {สุดท้าย multithread multithread1 = new Multithread (); multithread multithread2 = new multithread (); เธรดใหม่ (ใหม่ runnable () {public void run () {multithread1.printnum ("thread1", "a");}}) เริ่มต้น (); Thread.sleep (5000); System.out.println ("รอ 5 วินาทีเพื่อให้แน่ใจว่าเธรด 1 ถูกดำเนินการแล้ว!"); เธรดใหม่ (ใหม่ runnable () {public void run () {multithread2.printnum ("thread2", "b");}}) เริ่มต้น (); -ผลลัพธ์ผลลัพธ์:
THREAD1 TAG A, ตั้งค่า NUM Over! Thread1 Tag A, NUM = 100Wait 5 วินาทีเพื่อให้แน่ใจว่าเธรด 1 ถูกดำเนินการแล้ว! thread2 tag b ตั้งค่า num over! thread2 tag b, num = 0
จะเห็นได้ว่ามีสองวัตถุ: multithread1 และ multithread2 หากวัตถุหลายชิ้นใช้ล็อคเดียวกันผลลัพธ์ของการดำเนินการด้านบนควรเป็น: thread2 tag b, num = -100 ดังนั้นแต่ละวัตถุมีล็อคของวัตถุนั้น
ล็อคที่ได้รับจากคำหลักที่ซิงโครไนซ์เป็นล็อควัตถุแทนที่จะปฏิบัติต่อชิ้นส่วนของรหัสหรือวิธีการเป็นล็อค ดังนั้นในรหัสตัวอย่างด้านบนซึ่งเธรดซึ่งจะดำเนินการวิธีการที่ซิงโครไนซ์คีย์เวิร์ดก่อนเธรดจะถือล็อคของวัตถุที่วิธีการ เธรดได้รับล็อคสองตัวที่แตกต่างกันของวัตถุสองชิ้นที่แตกต่างกันและเติมเต็มซึ่งกันและกัน
ดังนั้นในสถานการณ์ปกติจะต้องมีสถานการณ์ที่วัตถุทั้งหมดจะทำงานในการนับตัวแปรดังนั้นจะนำไปใช้อย่างไร มันง่ายมากที่จะเพิ่มแบบคงที่ เรารู้ว่าวัตถุทั้งหมดในคลาสนี้มีการอ้างอิงเหมือนกันไม่ว่าจะมีการสร้างอินสแตนซ์ของวัตถุจำนวนเท่าใดการโทรเป็นวิธีการและรหัสมีดังนี้ (รหัส D):
คลาสสาธารณะ multithread {ส่วนตัวคงที่ int num = 200; public static synchronized void printnum (String threadname, String tag) {if (tag.equals ("a")) {num = num - 100; System.out.println (threadname + "แท็ก a ตั้งค่า num over!"); } else {num = num - 200; System.out.println (threadname + "แท็ก b ตั้งค่า num over!"); } system.out.println (threadname + "tag" + tag + ", num =" + num); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น InterruptedException {สุดท้าย multithread multithread1 = new Multithread (); multithread multithread2 = new multithread (); เธรดใหม่ (ใหม่ runnable () {public void run () {multithread1.printnum ("thread1", "a");}}) เริ่มต้น (); Thread.sleep (5000); System.out.println ("รอ 5 วินาทีเพื่อให้แน่ใจว่าเธรด 1 ถูกดำเนินการแล้ว!"); เธรดใหม่ (ใหม่ runnable () {public void run () {multithread2.printnum ("thread2", "b");}}) เริ่มต้น (); -ผลลัพธ์ผลลัพธ์:
THREAD1 TAG A, ตั้งค่า NUM Over! Thread1 Tag A, NUM = 100Wait 5 วินาทีเพื่อให้แน่ใจว่าเธรด 1 ถูกดำเนินการแล้ว! thread2 tag b, ตั้งค่า num over! thread2 tag b, num = -100
จะเห็นได้ว่าการเพิ่มการปรับเปลี่ยนแบบคงที่ไปยังตัวแปรและวิธีการสามารถตระหนักถึงสถานการณ์ที่เราต้องการ นอกจากนี้ยังแสดงให้เห็นว่าสำหรับวิธีการดัดแปลงหรือตัวแปรแบบคงที่แบบไม่คงที่ซึ่งเป็นวัตถุที่ถูกล็อค
6. ล็อควัตถุแบบซิงโครนัสและอะซิงโครนัส
(1) ซิงโครไนซ์
แนวคิดของการซิงโครไนซ์คือการแบ่งปัน เราจำเป็นต้องรู้ว่าคำว่า "การแบ่งปัน" ไม่ใช่ทรัพยากรที่ใช้ร่วมกันไม่จำเป็นต้องซิงโครไนซ์นั่นคือไม่จำเป็นต้องล็อค
วัตถุประสงค์ของการซิงโครไนซ์คือเพื่อให้แน่ใจว่าความปลอดภัยของเธรด ในความเป็นจริงเพื่อความปลอดภัยของด้ายต้องพบคุณลักษณะพื้นฐานสองประการที่สุด: ความผิดปกติและการมองเห็น
(2) อะซิงโครไนซ์: อะซิงโครไนซ์
แนวคิดของการเกิดแบบอะซิงโครนัสคือความเป็นอิสระโดยไม่มีข้อ จำกัด ใด ๆ ระหว่างกันและไม่มีความสัมพันธ์ระหว่างทั้งสอง
(3) รหัสตัวอย่าง:
คลาสสาธารณะ myObject {วิธีการเป็นโมฆะสาธารณะ () {system.out.println (thread.currentthread (). getName ()); } โมฆะคงที่สาธารณะหลัก (สตริง [] args) {สุดท้าย myObject myObject = new myObject (); เธรด t1 = เธรดใหม่ (ใหม่ runnable () {public void run () {myobject.method ();}}, "t1"); เธรด t2 = เธรดใหม่ (ใหม่ runnable () {public void run () {myobject.method ();}}, "t2"); t1.start (); t2.start (); -ในรหัสข้างต้นเมธอด () เป็นวิธีการแบบอะซิงโครนัส
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับการแก้ปัญหาเริ่มต้นกับแนวคิดของการทำเกลียวกระบวนการและซิงโครไนซ์ในมัลติเธรด Java ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้และชี้ให้เห็นและบรรณาธิการจะตอบกลับทุกคนในเวลา