ความเข้าใจสั้น ๆ เกี่ยวกับความแตกต่างระหว่างกระบวนการและเธรดในระบบปฏิบัติการ:
กระบวนการ: แต่ละกระบวนการมีรหัสอิสระและพื้นที่ข้อมูล (บริบทกระบวนการ) และการสลับระหว่างกระบวนการจะมีค่าใช้จ่ายขนาดใหญ่ กระบวนการมีเธรด 1-N (กระบวนการเป็นหน่วยที่เล็กที่สุดในการจัดสรรทรัพยากร)
เธรด: เธรดประเภทเดียวกันรหัสแชร์และพื้นที่ข้อมูล แต่ละเธรดมีสแต็กที่ใช้งานอิสระและตัวนับโปรแกรม (PC) และค่าใช้จ่ายในการสลับเธรดมีขนาดเล็ก (เธรดเป็นหน่วยที่เล็กที่สุดของการกำหนดเวลา CPU)
เช่นเดียวกับกระบวนการเธรดแบ่งออกเป็นห้าขั้นตอน: การสร้าง, พร้อม, วิ่ง, การบล็อก, การปิดกั้นและการยกเลิก
Multi-Process หมายความว่าระบบปฏิบัติการสามารถทำงานได้หลายงาน (โปรแกรม) ในเวลาเดียวกัน
MultithReading หมายถึงสตรีมตามลำดับหลายรายการที่ดำเนินการในโปรแกรมเดียวกัน ก่อนอื่นการดำเนินการออมเงินและการถอนเงินควรได้รับการขนย้ายและอาจมีลูกค้าจำนวนมาก ซึ่งหมายความว่าจะต้องมีหลายเธรดและหลายเธรดร่วมกันดำเนินการธนาคารและจำนวนเงินของธนาคารจะต้องมีการซิงโครไนซ์ โดยการรับรองความปลอดภัยของด้ายเท่านั้น
ดังนั้นขอใส่ตัวอย่างนี้ของรหัสนี้ที่นี่ หากมีบางอย่างผิดปกติโปรดชี้ให้เห็น เพราะชายชราถามเกี่ยวกับรหัสมัลติเธรดนี้
ก่อนอื่นธนาคารการสร้างโมเดลวัตถุนี้
แพ็คเกจ com.lxk.threadtest.bank;/*** โมเดลธนาคารแอตทริบิวต์จำนวนเงินทั้งหมด * <p> * * @author lxk ในปี 2017/6/26 */ธนาคารชั้นเรียนสาธารณะ {/** * ให้เงินทุนเริ่มต้นธนาคารมิฉะนั้นคุณจะทำธุรกิจได้อย่างไร */private int sum = 200; // สิ่งนี้ไม่เคยใช้เช่นนี้ แต่มันก็เป็นกลไกการล็อคที่ถูกต้อง: ซิงโครไนซ์บล็อกรหัส // object obj = วัตถุใหม่ (); /*** ประหยัดเงิน* หากคุณไม่ได้เพิ่ม [การซิงโครไนซ์-ฟังก์ชั่นซิงค์] ปัญหาด้านความปลอดภัยแบบมัลติเธรดจะเกิดขึ้น */โมฆะที่ซิงโครไนซ์สาธารณะเพิ่ม (int n) {// ซิงโครไนซ์ (obj) {sum = sum + n; ลอง {thread.sleep (10);} catch (ข้อยกเว้นไม่สนใจ) {} // เมื่อจำนวนครั้งที่ประหยัดเงินมากขึ้น System.out.println (thread.currentthread (). getName () + "... sum =" + sum); //}}/*** ถอนเงิน* หากคุณไม่เพิ่ม */โมฆะที่ซิงโครไนซ์สาธารณะลด (int n) {ถ้า (sum - n> = 0) {sum = sum - n;} else {system.out.println ("เงินของธนาคารไม่เพียงพอ!");} ลอง {ด้าย. เงิน. System.out.println (thread.currentthread (). getName () + "... sum =" + sum);}}มีสองวิธีในรหัส: บันทึกและดึงข้อมูลทั้งสองวิธีนี้และจำนวนทั้งหมดและบางคนแสดงความคิดเห็นรหัส นั่นเป็นเรื่องง่ายและเข้าใจง่ายล็อคแบบมัลติเธรดซึ่งกันและกันร่วมกันและทำให้มั่นใจได้ว่าการซิงโครไนซ์ระหว่างเธรด
อย่างไรก็ตามนี่เป็นวิธีที่ไม่บ่อยนัก วิธีที่ใช้กันทั่วไปคือการใช้คำหลักที่ซิงโครไนซ์เพื่อแก้ไขวิธีการซิงโครไนซ์
รูปแบบของวัตถุไคลเอนต์
แพ็คเกจ com.lxk.threadtest.bank;/*** ลูกค้าใช้อินเตอร์เฟส runnable () และหลายคนสามารถประหยัดเงินร่วมกัน** @author lxk บน 2017/6/26*/ลูกค้าชั้นเรียนสาธารณะใช้งานได้ ธนาคารธนาคาร;/*** ประเภทการดำเนินงานสำหรับเงินการออมหรือการถอน*/ประเภทสตริงส่วนตัว;/*** จำนวนการดำเนินงานเป็นจำนวนบวกในเชิงบวก*/เวลา int ส่วนตัว;/*** เท่าไหร่ที่จะประหยัดหรือถอนเงิน*/เงินส่วนตัว; ลูกค้าสาธารณะ () {} ลูกค้าสาธารณะ (ธนาคารประเภทนี้ money;}@การแทนที่โมฆะสาธารณะเรียกใช้ () {สำหรับ (int x = 0; x <เวลา; x ++) {ถ้า (type_add.equals (ประเภท)) {bank.add (เงิน);} อื่นถ้า (type_reduce.equals (ประเภท))ในฐานะที่เป็นวัตถุลูกค้าเนื่องจากลูกค้าจำนวนมากสามารถเข้าถึงธนาคารได้ในเวลาเดียวกันการดำเนินการของการออมและการถอนเงินจะถูกนำไปใช้โดยใช้เธรด
แอตทริบิวต์ถูกสร้างขึ้นเพื่อส่งผ่านค่า
วิธีหลัก
แพ็คเกจ com.lxk.threadtest.bank;/** * อินสแตนซ์แบบมัลติเธรดของธนาคารฝากเงิน * <p> * [ข้อกำหนด:] * ธนาคารมีห้องนิรภัย * มีผู้ฝากเงินสองคนที่ฝากหรือถอนตัว n * 100 ตามลำดับ * วัตถุประสงค์: มีปัญหาด้านความปลอดภัยกับโปรแกรมนี้หรือไม่? ถ้าเป็นเช่นนั้นจะแก้ปัญหาได้อย่างไร? * <p> * [วิธีการค้นหาปัญหา:] * 1. ชัดเจนว่ารหัสใดเป็นรหัสมัลติเธรด * 2. แบ่งปันข้อมูลอย่างชัดเจน * 3. ชัดเจนว่าคำสั่งใดในรหัสหลายเธรดทำงานบนข้อมูลที่ใช้ร่วมกัน * * @author lxk เมื่อ 2017/6/26 */ชั้นเรียนสาธารณะหลัก {โมฆะสาธารณะคงที่หลัก (สตริง [] args) {// ธนาคารหนึ่งธนาคารและธนาคารลูกค้าหลายธนาคาร = ธนาคารใหม่ (); เวลา int = 10,000; customer.type_reduce, เวลา, เงิน); เธรด t1 = เธรดใหม่ (c1); เธรด t2 = เธรดใหม่ (c2); t1.start (); t2.start ();}}เอฟเฟกต์การทำงานจริงของรหัสข้างต้นแสดงในรูปด้านล่าง
หากจำนวนครั้งของการฝากเงินและการถอนเงินมีขนาดเล็กคุณอาจเห็นว่าสองเธรดมีลำดับ ดังนั้นเรามีจำนวนครั้งที่มากขึ้น จากนั้นเราจะเห็นสถานการณ์ดังที่แสดงในรูป เธรด 1 ถอนเงินและเมื่อเธรด 0 ประหยัดเงินคุณจะเห็นว่าสองเธรดจะถูกดำเนินการ interleaved ทั้งที่เก็บและการถอนและไม่มีรูปแบบ
สิ่งนี้ทำให้มั่นใจได้ว่าการซิงโครไนซ์ข้อมูล
สำหรับวิธีการออกจากการซิงโครไนซ์นั่นคือปรากฏการณ์ที่ผิดปกติ
คุณสามารถลบคำหลักที่ซิงโครไนซ์ของวิธีเพิ่มลดจำนวนครั้งและเปลี่ยนเป็น 3 ครั้งและตั้งค่าเริ่มต้นเป็น 0 เป็น 0 ลองรหัสอีกครั้ง
คุณจะพบปรากฏการณ์ async ที่เรียกว่า
ผลลัพธ์ของการไม่ซิงโครไนซ์ทางด้านขวาของรูปด้านบนคือคนสองคนประหยัด 100 ในแต่ละครั้งสามครั้ง จำนวนทั้งหมดได้รับหรือไม่? 100,200,300,400,500,600 ใช้เวลานาน
อย่างไรก็ตามผลการดำเนินการไม่ได้
ในเวลานี้หากคุณเพิ่มวิธีการซิงโครไนซ์ลงในวิธีการเพิ่มผลลัพธ์ของกราฟทางด้านซ้ายจะปรากฏขึ้นซึ่งเป็นผลลัพธ์ที่ถูกต้อง
ฉันเพิ่มวิธีการอื่นเพื่อประโยชน์ในการดำรงอยู่และการถอน รหัสกลายเป็นสิ่งที่ดูเหมือนข้างต้น
นี่คือตัวอย่างเกือบทั้งหมดของการซิงโครไนซ์ระหว่างเธรด
ฉันจะบันทึกรหัสสั้น ๆ เมื่อใช้แล้วคุณสามารถนำมันออกมาได้ในไม่กี่นาที
สรุป
ข้างต้นเป็นรหัสที่สมบูรณ์ของบทความนี้เกี่ยวกับการจำลองปัญหาการซิงโครไนซ์ Java multithreaded โดยใช้การถอนธนาคารเป็นตัวอย่าง ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงเว็บไซต์นี้ต่อไปได้:
ตัวอย่างการเขียนโปรแกรม Java Multithreaded
หลักการและการใช้งานของตัวจับเวลา Java Multithreaded Timer
Java เข้าใจมัลติเธรดด้วยการขายตั๋ว
หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!