เอกสาร Java กล่าวว่า:
เป็นไปไม่ได้ที่การเรียกใช้วิธีการซิงโครไนซ์สองครั้งบนวัตถุเดียวกันเพื่อแทรกสอด
สิ่งนี้หมายความว่าสำหรับวิธีการคงที่? เนื่องจากวิธีการคงที่ไม่มีวัตถุที่เกี่ยวข้องคำหลักที่ถูกซิงโครไนซ์จะล็อคในชั้นเรียนแทนที่จะเป็นวัตถุหรือไม่
เอกสาร Java กล่าวว่า:
เป็นไปไม่ได้ที่การเรียกใช้วิธีการซิงโครไนซ์สองครั้งบนวัตถุเดียวกันเพื่อแทรกสอด
สิ่งนี้หมายความว่าสำหรับวิธีการคงที่? เนื่องจากวิธีการคงที่ไม่มีวัตถุที่เกี่ยวข้องคำหลักที่ถูกซิงโครไนซ์จะล็อคในชั้นเรียนแทนที่จะเป็นวัตถุหรือไม่
คำตอบ:
เนื่องจากวิธีการคงที่ไม่มีวัตถุที่เกี่ยวข้อง คำหลักที่ถูกซิงโครไนซ์จะล็อคในชั้นเรียนแทนที่จะเป็นวัตถุหรือไม่
ใช่. :)
this
เป็นล็อคที่ได้มาจากวิธีการเช่น - โปรดแก้ไขออสการ์
เพียงเพื่อเพิ่มรายละเอียดเล็ก ๆ น้อย ๆ ให้กับคำตอบของออสการ์ (รวบรัด!) ส่วนที่เกี่ยวข้องในข้อกำหนดภาษา Java คือ8.4.3.6, 'วิธีการซิงโครไนซ์' :
วิธีการซิงโครไนซ์จะได้รับมอนิเตอร์ ( §17.1 ) ก่อนที่จะดำเนินการ สำหรับวิธีการเรียน (คงที่), จอภาพที่เกี่ยวข้องกับวัตถุชั้นเรียนสำหรับชั้นเรียนของวิธีการที่ถูกนำมาใช้ สำหรับวิธีอินสแตนซ์จะใช้มอนิเตอร์ที่เชื่อมโยงกับสิ่งนี้ (วัตถุซึ่งเป็นวิธีการที่เรียกใช้)
ประเด็นหนึ่งที่คุณต้องระวัง (โปรแกรมเมอร์ส่วนใหญ่มักจะตกอยู่ในกับดัก) นั่นคือไม่มีการเชื่อมโยงระหว่างวิธีการทำข้อมูลให้ตรงกันแบบคงที่และวิธีการทำข้อมูลให้ตรงกันแบบไม่คงที่เช่น:
class A {
static synchronized f() {...}
synchronized g() {...}
}
หลัก:
A a = new A();
หัวข้อที่ 1:
A.f();
หัวข้อที่ 2:
a.g();
f () และ g () จะไม่ถูกซิงโครไนซ์ซึ่งกันและกันและทำให้สามารถทำงานได้พร้อมกันโดยสิ้นเชิง
synchronized (MyClass.class) {...}
.
ยกเว้นว่าคุณใช้ g () ดังต่อไปนี้:
g() {
synchronized(getClass()) {
...
}
}
ฉันพบว่ารูปแบบนี้มีประโยชน์เช่นกันเมื่อฉันต้องการใช้การยกเว้นซึ่งกันและกันระหว่างอินสแตนซ์ที่แตกต่างกันของวัตถุ (ซึ่งจำเป็นสำหรับการเข้าถึงทรัพยากรภายนอกเช่น)
getClass()
ส่งคืนประเภทรันไทม์ ; ถ้าคุณคลาสย่อยคลาสแล้วคลาสพาเรนต์และคลาสลูกจะซิงโครไนซ์บนการล็อกต่างกัน synchronized(MyClass.class)
เป็นวิธีที่จะไปหากคุณต้องการให้แน่ใจว่าทุกกรณีใช้การล็อคเดียวกัน
ดูที่หน้าเอกสารของ oracle เกี่ยวกับ Intrinsic Locks and Synchronization
คุณอาจสงสัยว่าเกิดอะไรขึ้นเมื่อมีการเรียกใช้วิธีการซิงโครไนซ์แบบคงที่เนื่องจากวิธีการแบบสแตติกเชื่อมโยงกับคลาสไม่ใช่วัตถุ ในกรณีนี้ด้ายได้มาล็อคที่แท้จริงสำหรับวัตถุชั้นเกี่ยวข้องกับการเรียน ดังนั้นการเข้าถึงเขตสถิตชั้นของถูกควบคุมโดยล็อคที่แตกต่างจากล็อคสำหรับอินสแตนซ์ของคลาสใด ๆ
วิธีการคงที่ยังมีวัตถุที่เกี่ยวข้อง มันเป็นไฟล์ Class.class ในชุดเครื่องมือ JDK เมื่อไฟล์. class โหลดลงในหน่วยความจำ Class.class จะสร้างอินสแตนซ์ของมันเรียกว่าวัตถุแม่แบบ
เช่น: - เมื่อคุณพยายามที่จะสร้างวัตถุจากระดับลูกค้าที่มีอยู่เช่น
Customer c = new Customer();
โหลด Customer.class เป็น RAM ในขณะนั้น Class.class ในชุดเครื่องมือ JDK สร้างวัตถุที่เรียกว่าวัตถุแม่แบบและโหลด Customer.class ลงในวัตถุแม่แบบนั้นสมาชิกแบบคงที่ของ Customer.class นั้นกลายเป็นคุณลักษณะและวิธีการในวัตถุแม่แบบนั้น
ดังนั้นวิธีการหรือคุณลักษณะแบบคงที่จึงมีวัตถุ
ตัวอย่างด้านล่างให้ความชัดเจนมากขึ้นระหว่างคลาสและล็อควัตถุหวังว่าตัวอย่างด้านล่างจะช่วยให้ผู้อื่นเช่นกัน :)
ตัวอย่างเช่นเรามีวิธีการด้านล่างหนึ่งคลาสที่ได้รับและอื่น ๆ ได้รับล็อควัตถุ:
public class MultiThread {
public static synchronized void staticLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public synchronized void objLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
ดังนั้นตอนนี้เราสามารถมีสถานการณ์ต่อไปนี้:
เมื่อเธรดที่ใช้ออบเจ็กต์เดียวกันพยายามเข้าถึงobjLock
หรือ staticLock
วิธีเดียวกันในเวลาเดียวกัน (เช่นเธรดทั้งสองพยายามเข้าถึงวิธีเดียวกัน)
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
เมื่อเธรดที่ใช้ออบเจ็กต์เดียวกันพยายามเข้าถึงstaticLock
และobjLock
เมธอดในเวลาเดียวกัน (พยายามเข้าถึงวิธีอื่น ๆ )
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
เมื่อเธรดที่ใช้ออบเจ็กต์อื่นพยายามเข้าถึงstaticLock
วิธีการ
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
เมื่อเธรดที่ใช้ออบเจ็กต์อื่นพยายามเข้าถึงobjLock
วิธีการ
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
สำหรับผู้ที่ไม่คุ้นเคยวิธีการซิงโครไนซ์แบบคงที่ที่ถูกล็อกบนวัตถุคลาสเช่นสำหรับคลาสสตริงนั้น String.class ในขณะที่วิธีการซิงโครไนซ์จะล็อกอินสแตนซ์ปัจจุบันของวัตถุที่แสดงด้วยคำว่า เนื่องจากวัตถุทั้งสองนี้มีความแตกต่างกันจึงมีการล็อกที่แตกต่างกันดังนั้นในขณะที่หนึ่งเธรดกำลังดำเนินการกับวิธีการซิงโครไนซ์แบบคงที่เธรดอื่นใน java ไม่จำเป็นต้องรอให้เธรดนั้นส่งคืนแทน วิธีการทำข้อมูลให้ตรงกันแบบคงที่