หมายเหตุ : เดิมฉันโพสต์รหัส C # ในคำตอบนี้เพื่อวัตถุประสงค์ในการภาพประกอบเนื่องจาก C # ช่วยให้คุณสามารถส่งint
พารามิเตอร์โดยอ้างอิงกับref
คำหลัก ฉันตัดสินใจที่จะอัปเดตด้วยรหัส Java ตามกฎหมายจริงโดยใช้MutableInt
ชั้นหนึ่งที่ฉันพบใน Google เพื่อจัดเรียงโดยประมาณของสิ่งที่ref
ทำใน C # ฉันไม่สามารถบอกได้จริง ๆ ว่าสิ่งนั้นช่วยหรือทำร้ายคำตอบ ฉันจะบอกว่าฉันเองยังไม่ได้ทำการพัฒนา Java ทั้งหมด ดังนั้นสำหรับทั้งหมดที่ฉันรู้อาจมีวิธีสำนวนมากกว่านี้เพื่อแสดงจุดนี้
บางทีถ้าเราเขียนวิธีการที่จะทำสิ่งที่เท่าเทียมกันx++
มันจะทำให้ชัดเจนขึ้น
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
ขวา? เพิ่มค่าที่ส่งผ่านและส่งคืนค่าดั้งเดิมนั่นคือคำจำกัดความของโอเปอเรเตอร์หลังการทำ
ตอนนี้มาดูกันว่าพฤติกรรมนี้เล่นในโค้ดตัวอย่างของคุณได้อย่างไร:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)
ทำอะไร เพิ่มขึ้นx
ใช่ และจากนั้นส่งกลับสิ่งที่x
เป็นก่อนที่จะเพิ่มขึ้น x
ค่าตอบแทนนี้แล้วได้รับมอบหมายให้
ลำดับของค่าที่กำหนดให้x
คือ 0 จากนั้น 1 จากนั้น 0
สิ่งนี้อาจชัดเจนกว่านี้ถ้าเราเขียนข้างต้นอีกครั้ง:
MutableInt x = new MutableInt(); // x is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
x = temp; // Now x is 0 again.
การตรึงของคุณเกี่ยวกับความจริงที่ว่าเมื่อคุณแทนที่x
ทางด้านซ้ายของการมอบหมายข้างต้นด้วยy
"คุณจะเห็นได้ว่ามันเพิ่มขึ้นทีแรก x และคุณลักษณะในภายหลังเพื่อ y" ทำให้ฉันสับสน มันไม่ได้x
ถูกกำหนดให้y
; มันเป็นค่าที่ได้รับมอบหมายก่อนหน้าx
นี้ จริงๆแล้วการฉีดy
ทำให้สิ่งต่าง ๆ ไม่แตกต่างจากสถานการณ์ข้างต้น เราได้รับ:
MutableInt x = new MutableInt(); // x is 0.
MutableInt y = new MutableInt(); // y is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
y = temp; // y is still 0.
ดังนั้นชัดเจน: x = x++
ไม่มีผลต่อการเปลี่ยนแปลงค่าของ x มันทำให้ x มีค่า x 0เสมอแล้ว x 0 + 1 และ x 0อีกครั้ง
Update : อนึ่งเพื่อไม่ให้คุณสงสัยว่าx
เคยได้รับมอบหมายให้ 1 "ระหว่าง" การดำเนินการที่เพิ่มขึ้นและการมอบหมายในตัวอย่างข้างต้นฉันได้ขว้างการสาธิตอย่างรวดเร็วเพื่อแสดงให้เห็นว่าค่ากลางนี้ "มีอยู่จริง" แม้ว่ามันจะ ไม่ต้อง "เห็น" บนเธรดที่กำลังเรียกใช้งาน
การสาธิตเรียกx = x++;
เป็นวนซ้ำในขณะที่เธรดแยกต่างหากจะพิมพ์ค่าของx
คอนโซลอย่างต่อเนื่อง
public class Main {
public static volatile int x = 0;
public static void main(String[] args) {
LoopingThread t = new LoopingThread();
System.out.println("Starting background thread...");
t.start();
while (true) {
x = x++;
}
}
}
class LoopingThread extends Thread {
public @Override void run() {
while (true) {
System.out.println(Main.x);
}
}
}
ด้านล่างเป็นข้อความที่ตัดตอนมาจากผลลัพธ์ของโปรแกรมด้านบน สังเกตเห็นการเกิดขึ้นที่ผิดปกติของทั้ง 1s และ 0s
กำลังเริ่มต้นเธรดพื้นหลัง ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1