การล็อกคลาสและการล็อกวัตถุจะขัดแย้งกันหรือไม่ การล็อควัตถุและการล็อคส่วนตัวจะขัดแย้งกันหรือไม่ ภาพประกอบผ่านตัวอย่าง
1. ข้อตกลงที่เกี่ยวข้อง
เพื่อชี้แจงคำอธิบายต่อไปนี้ ก่อนอื่นเราจะจัดทำแบบแผนต่อไปนี้เกี่ยวกับคำจำกัดความที่เกี่ยวข้องของการล็อคที่เกี่ยวข้องกับบทความนี้:
1. Class lock: เพิ่มการล็อคแบบคงที่และแบบซิงโครไนซ์ให้กับวิธีการในโค้ด หรือส่วนของโค้ดแบบซิงโครไนซ์ (xxx.class) เช่น increament() ด้านล่าง
2. การล็อควัตถุ: เพิ่มการล็อคแบบซิงโครไนซ์ให้กับวิธีการในโค้ด หรือส่วนของโค้ดที่ซิงโครไนซ์(นี้) เช่น synOnMethod() และ synInMethod() ด้านล่าง
3. การล็อคส่วนตัว: ประกาศคุณสมบัติส่วนตัว เช่น การล็อควัตถุส่วนตัวภายในคลาส และซิงโครไนซ์(ล็อค) ส่วนโค้ดที่จำเป็นต้องล็อค เช่น synMethodWithObj() ด้านล่าง
2. รหัสทดสอบ
1. เขียนคลาสเริ่มต้น ObjectLock
คัดลอกรหัสรหัสดังต่อไปนี้:
ObjectLock คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
System.out.println("เวลาเริ่มต้น = " + System.currentTimeMillis()+"ms");
การทดสอบ LockTestClass = LockTestClass ใหม่ ();
สำหรับ (int i = 0; i <3; i++) {
เธรดเธรด = ObjThread ใหม่ (ทดสอบ, i);
เธรด.เริ่มต้น();
-
-
-
2. เขียนคลาสเธรด ObjThread เพื่อเริ่มวิธีการซิงโครไนซ์ (โปรดทราบว่าวิธีการรันอาจถูกปรับเปลี่ยนสำหรับการทดสอบที่แตกต่างกัน)
คัดลอกรหัสรหัสดังต่อไปนี้:
ObjThread คลาสสาธารณะขยายเธรด {
ล็อค LockTestClass;
int i = 0;
ObjThread สาธารณะ (ล็อค LockTestClass, int i) {
this.lock = ล็อค;
นี่.ฉัน = ฉัน;
-
โมฆะสาธารณะวิ่ง () {
//วิธีการแบบไม่มีล็อค
//lock.noSynMethod(this.getId(),นี่);
//การล็อควัตถุวิธีที่ 1 โดยใช้ synInMethod ที่ซิงโครไนซ์
lock.synInMethod();
//การล็อควัตถุวิธีที่ 2 โดยใช้วิธีซิงโครไนซ์ (นี้)
//lock.synOnMethod();
//วิธีการล็อคส่วนตัวโดยใช้วิธีซิงโครไนซ์ (วัตถุ)
//lock.synMethodWithObj();
//วิธีการล็อคคลาสโดยใช้วิธีการเพิ่มค่าแบบซิงโครไนซ์แบบคงที่
LockTestClass.increase();
-
-
3. เขียนคลาสทดสอบการล็อคอีกคลาส LockTestClass รวมถึงวิธีการล็อคต่างๆ
คัดลอกรหัสรหัสดังต่อไปนี้:
LockTestClass คลาสสาธารณะ {
//ใช้สำหรับนับการล็อคคลาส
int คงที่ส่วนตัว i = 0;
//ล็อคส่วนตัว
วัตถุวัตถุส่วนตัว = วัตถุใหม่ ();
-
* <p>
* วิธีไร้ล็อค
-
* @param threadID
* เธรด @param
-
โมฆะสาธารณะ noSynMethod (threadID แบบยาว, เธรด ObjThread) {
System.out.println("nosyn: คลาส obj คือ " + thread + ", threadId คือ"
+ รหัสเธรด);
-
-
* วิธีล็อควัตถุ 1
-
โมฆะซิงโครไนซ์สาธารณะ synOnMethod () {
System.out.println("synOnMethod เริ่มต้น" + ", เวลา = "
+ System.currentTimeMillis() + "ms");
พยายาม {
ด้าย.นอน(2000L);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.println("synOnMethod สิ้นสุด");
-
-
* การล็อควัตถุวิธีที่ 2 ใช้การซิงโครไนซ์ (สิ่งนี้) เพื่อล็อค
-
โมฆะสาธารณะ synInMethod () {
ซิงโครไนซ์ (สิ่งนี้) {
System.out.println("synInMethod เริ่มต้น" + ", เวลา = "
+ System.currentTimeMillis() + "ms");
พยายาม {
ด้าย.นอน(2000L);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.println("synInMethod สิ้นสุด");
-
-
-
* วิธีการล็อควัตถุ 3
-
โมฆะสาธารณะ synMethodWithObj () {
ซิงโครไนซ์ (วัตถุ) {
System.out.println("synMethodWithObj เริ่มต้น" + ", เวลา = "
+ System.currentTimeMillis() + "ms");
พยายาม {
ด้าย.นอน(2000L);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.println("synMethodWithObj สิ้นสุด");
-
-
-
* ล็อคชั้นเรียน
-
โมฆะการซิงโครไนซ์สาธารณะแบบคงที่เพิ่มขึ้น () {
System.out.println("คลาสซิงโครไนซ์ i = " + i + ", เวลา = "
+ System.currentTimeMillis() + "ms");
ฉัน++;
พยายาม {
ด้าย.นอน(2000L);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.println("คลาสซิงโครไนซ์สิ้นสุด");
-
-
3. ผลการทดสอบ
1. ในการทดสอบการล็อกคลาสและการล็อกอ็อบเจ็กต์ ให้แก้ไขวิธีการรันของ ObjectThread ดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะสาธารณะวิ่ง () {
//วิธีการแบบไม่มีล็อค
//lock.noSynMethod(this.getId(),นี่);
//การล็อควัตถุวิธีที่ 1 โดยใช้ synInMethod ที่ซิงโครไนซ์
lock.synInMethod();
//วิธีล็อควัตถุ 2 โดยใช้วิธีซิงโครไนซ์ (นี้)
//lock.synOnMethod();
// วิธีการล็อคส่วนตัวโดยใช้วิธีซิงโครไนซ์ (วัตถุ)
//lock.synMethodWithObj();
//วิธีการล็อคคลาสโดยใช้วิธีการเพิ่มค่าแบบซิงโครไนซ์แบบคงที่
LockTestClass.increament();
-
ขั้วเอาท์พุท:
คัดลอกรหัสรหัสดังต่อไปนี้:
เวลาเริ่มต้น = 1413101360231ms
synInMethod เริ่มต้น เวลา = 1413101360233ms
synInMethod สิ้นสุดลง
คลาสซิงโครไนซ์ i = 0, เวลา = 1413101362233ms
synInMethod เริ่มต้น เวลา = 1413101362233ms
คลาสซิงโครไนซ์สิ้นสุด
synInMethod สิ้นสุดลง
คลาสซิงโครไนซ์ i = 1, เวลา = 1413101364233ms
synInMethod เริ่มต้น เวลา = 1413101364233ms
คลาสซิงโครไนซ์สิ้นสุด
synInMethod สิ้นสุดลง
คลาสซิงโครไนซ์ i = 2, เวลา = 1413101366234ms
คลาสซิงโครไนซ์สิ้นสุด
คุณจะเห็นว่าวิธีการล็อคอ็อบเจ็กต์ (synInMothod) นั้นเร็วกว่าวิธีการล็อคคลาส 2 วินาที (เพิ่มขึ้น) เมื่อเริ่มต้นครั้งแรก นี่เป็นเพราะเมื่อดำเนินการ synInMehtod มันจะพักเป็นเวลา 2 วินาทีจากนั้นจึงดำเนินการเพิ่มขึ้น และทั้งสองนี้ วิธีการใช้เธรดเดียวกัน ดังนั้น จะช้าลง 2 วินาที หากเพิ่มไว้หน้า synInMethod ในการทำงาน การเพิ่มขึ้นจะเร็วขึ้น 2 วินาทีเมื่อเริ่มต้นเป็นครั้งแรก
เมื่อเริ่มต้นวิธีการล็อคคลาส วิธีการล็อคอ็อบเจ็กต์ของเธรดอื่นก็เริ่มต้นเกือบพร้อมกัน แสดงให้เห็นว่าทั้งสองไม่ได้ใช้การล็อคเดียวกันและจะไม่มีการแข่งขัน
สรุป: การล็อคคลาสและการล็อคออบเจ็กต์จะไม่แข่งขันกัน และวิธีการล็อคจะไม่ส่งผลกระทบต่อกัน
2. การล็อคส่วนตัวและการล็อคอ็อบเจ็กต์ วิธีการรันของ ObjectThread ได้รับการแก้ไขดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะสาธารณะวิ่ง () {
//วิธีการแบบไม่มีล็อค
//lock.noSynMethod(this.getId(),นี่);
//การล็อควัตถุวิธีที่ 1 โดยใช้ synInMethod ที่ซิงโครไนซ์
lock.synInMethod();
//การล็อควัตถุวิธีที่ 2 โดยใช้วิธีซิงโครไนซ์ (นี้)
//lock.synOnMethod();
// วิธีการล็อคส่วนตัวโดยใช้วิธีซิงโครไนซ์ (วัตถุ)
lock.synMethodWithObj();
//วิธีการล็อคคลาสโดยใช้วิธีการเพิ่มค่าแบบซิงโครไนซ์แบบคงที่
//LockTestClass.increament();
-
ขั้วเอาท์พุท:
คัดลอกรหัสรหัสดังต่อไปนี้:
เวลาเริ่มต้น = 1413121912406ms
synInMethod เริ่มต้น เวลา = 1413121912407ms
synInMethod สิ้นสุดลง
synMethodWithObj เริ่มต้น เวลา = 1413121914407ms
synInMethod เริ่มต้น เวลา = 1413121914407ms
synInMethod สิ้นสุดลง
synMethodWithObj สิ้นสุด
synInMethod เริ่มต้น เวลา = 1413121916407ms
synMethodWithObj เริ่มต้น เวลา = 1413121916407ms
synInMethod สิ้นสุดลง
synMethodWithObj สิ้นสุด
synMethodWithObj เริ่มต้น เวลา = 1413121918407ms
synMethodWithObj สิ้นสุด
คล้ายกันมากกับการล็อคคลาสและการล็อควัตถุ
สรุป: การล็อคส่วนตัวและการล็อควัตถุจะไม่แข่งขันกัน และวิธีการล็อคจะไม่ส่งผลกระทบต่อกัน
3. การซิงโครไนซ์จะถูกเพิ่มโดยตรงไปยังวิธีการและการซิงโครไนซ์ (สิ่งนี้) และวิธีการรันของ ObjectThread ได้รับการแก้ไขดังต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะสาธารณะวิ่ง () {
//วิธีการแบบไม่มีล็อค
//lock.noSynMethod(this.getId(),นี่);
//การล็อควัตถุวิธีที่ 1 โดยใช้ synInMethod ที่ซิงโครไนซ์
lock.synInMethod();
//วิธีล็อควัตถุ 2 โดยใช้วิธีซิงโครไนซ์ (นี้)
lock.synOnMethod();
//วิธีการล็อคส่วนตัวโดยใช้วิธีซิงโครไนซ์ (วัตถุ)
//lock.synMethodWithObj();
//วิธีการล็อคคลาสโดยใช้วิธีการเพิ่มค่าแบบซิงโครไนซ์แบบคงที่
//LockTestClass.increament();
-
ขั้วเอาท์พุท:
คัดลอกรหัสรหัสดังต่อไปนี้:
เวลาเริ่มต้น = 1413102913278ms
synInMethod เริ่มต้น เวลา = 1413102913279ms
synInMethod สิ้นสุดลง
synInMethod เริ่มต้น เวลา = 1413102915279ms
synInMethod สิ้นสุดลง
synOnMethod เริ่มต้น เวลา = 1413102917279ms
synOnMethod สิ้นสุดลง
synInMethod เริ่มต้น เวลา = 1413102919279ms
synInMethod สิ้นสุดลง
synOnMethod เริ่มต้น เวลา = 1413102921279ms
synOnMethod สิ้นสุดลง
synOnMethod เริ่มต้น เวลา = 1413102923279ms
synOnMethod สิ้นสุดลง
อย่างที่คุณเห็น เอาต์พุตสองตัวเรียงลำดับกันอย่างเคร่งครัด (แน่นอนว่า synInMethod หรือ synOnMethod จะถูกรันก่อนเมื่อดำเนินการอีกครั้งไม่ได้ถูกกำหนด ขึ้นอยู่กับว่าใครได้รับการล็อค)
สรุป: ซิงโครไนซ์เพิ่มโดยตรงกับเมธอดและซิงโครไนซ์ (สิ่งนี้) ทั้งล็อคออบเจ็กต์ปัจจุบัน วิธีการล็อคทั้งสองนั้นมีความสัมพันธ์แบบแข่งขันกัน และมีเพียงวิธีเดียวเท่านั้นที่สามารถดำเนินการได้ในเวลาเดียวกัน