"สวัสดี Amigo! เมื่อวานเราได้พูดถึงประโยชน์และความสะดวกของมัลติเธรด ตอนนี้ได้เวลาดูข้อเสียแล้ว โชคไม่ดีที่พวกมันไม่เล็ก"

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

การตีความใหม่นี้ไม่ได้ยกเลิกการตีความครั้งแรก พวกเขายังคงเป็นวัตถุและยังคงเรียกวิธีการของกันและกัน แต่เราต้องจำไว้ว่ามีหลายเธรด และแต่ละเธรดมีหน้าที่หรือภารกิจของตัวเอง

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

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

รหัสของเธรดแรก รหัสของเธรดที่สอง
System.out.print ("Nick is");
System.out.print ("");
System.out.print ("15");
System.out.print ("");
System.out.print ("years old");
System.out.println ();
System.out.print ("Lena is");
System.out.print ("");
System.out.print ("21");
System.out.print ("");
System.out.print ("years old");
System.out.println ();
สิ่งที่เราคาดว่าจะแสดง
นิคอายุ 15 ปี
ลีนาอายุ 21 ปี
การดำเนินการโค้ดจริง รหัสของเธรดแรก รหัสของเธรดที่สอง
System.out.print ("Nick is");
System.out.print ("Lena is");
System.out.print (" ");
System.out.print (" ");
System.out.print ("15");
System.out.print ("21");
System.out.print (" ");
System.out.print (" ");
System.out.print ("years old");
System.out.println ();
System.out.print ("years old");
System.out.println ();
System.out.print ("Nick is");
//other thread is running
//other thread is running
System.out.print (" ");
System.out.print ("15");
//other thread is running
//other thread is running
System.out.print (" ");
System.out.print ("years old");
System.out.println ();
//other thread is running
//other thread is running
//other thread is running
System.out.print ("Lena is");
System.out.print (" ");
//other thread is running
//other thread is running
System.out.print ("21");
System.out.print (" ");
//other thread is running
//other thread is running
//other thread is running
System.out.print ("years old");
System.out.println ();
สิ่งที่แสดงจริง
Nick ชื่อ Lena   อายุ15 ปี  21  ปี

และนี่คืออีกตัวอย่างหนึ่ง:

รหัส คำอธิบาย
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";
public void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
วิธีการสลับswapค่าของตัวแปรname1และname2

จะเกิดอะไรขึ้นหากมีการเรียกจากสองเธรดในเวลาเดียวกัน

การดำเนินการโค้ดจริง รหัสของเธรดแรก รหัสของเธรดที่สอง
String s1 = name1; //Ally
name1 = name2; //Lena
String s2 = name1; //Lena(!)
name1 = name2; //Lena
name2 = s1; //Ally
name2 = s2; //Lena
String s1 = name1;
name1 = name2;
//other thread is running
//other thread is running
name2 = s1;
//other thread is running
//other thread is running
//other thread is running
String s2 = name1;
name1 = name2;
//other thread is running
name2 = s2;
บรรทัดล่างสุด
ตัวแปรทั้งสองมีค่า «Lena»
วัตถุ «พันธมิตร» ไม่ได้สร้างมันขึ้นมา มันหายไป

"ใครจะคาดคิดว่าข้อผิดพลาดเช่นนี้เกิดขึ้นได้ด้วยการดำเนินการมอบหมายง่ายๆ เช่นนี้!"

"ใช่ ปัญหานี้มีทางแก้ไข แต่เราจะพูดถึงเรื่องนี้ในภายหลัง คอของฉันแห้ง"