Java Synchronized Block สำหรับ. class


103

รหัสจาวาหมายถึงอะไร? จะได้รับการล็อควัตถุทั้งหมดของMyClass?

synchronized(MyClass.class) {
   //is all objects of MyClass are thread-safe now ??
}

และโค้ดด้านบนแตกต่างจากโค้ดนี้อย่างไร:

synchronized(this) {
   //is all objects of MyClass are thread-safe now ??
}

ที่เกี่ยวข้อง: stackoverflow.com/questions/437620/…
finnw

คำตอบ:


144

ตัวอย่างข้อมูล synchronized(X.class)ใช้อินสแตนซ์คลาสเป็นมอนิเตอร์ เนื่องจากมีอินสแตนซ์คลาสเดียวเท่านั้น (อ็อบเจ็กต์ที่แสดงข้อมูลเมตาของคลาสที่รันไทม์) หนึ่งเธรดจึงสามารถอยู่ในบล็อกนี้ได้

ด้วยsynchronized(this)บล็อกจะถูกปกป้องโดยอินสแตนซ์ สำหรับทุกอินสแตนซ์จะมีเพียงเธรดเดียวเท่านั้นที่เข้าสู่บล็อก

synchronized(X.class)ใช้เพื่อให้แน่ใจว่ามีเธรดเดียวในบล็อก synchronized(this)ตรวจสอบให้แน่ใจว่ามีหนึ่งเธรดต่ออินสแตนซ์ หากสิ่งนี้ทำให้รหัสจริงในบล็อกเธรดปลอดภัยขึ้นอยู่กับการนำไปใช้งาน ถ้าเปลี่ยนสถานะเฉพาะของอินสแตนซ์synchronized(this)ก็เพียงพอแล้ว


6
"เนื่องจากเธรดจำนวนมากสามารถเข้าสู่บล็อกได้ตามที่มีอินสแตนซ์" หมายความว่ารูปแบบที่สองทำหน้าที่เป็นเซมาฟอร์ซึ่งไม่เป็นความจริง คุณควรพูดว่า: "ซิงโครไนซ์ (สิ่งนี้) เพื่อให้แน่ใจว่าเธรดเดียวเท่านั้นที่สามารถเข้าสู่บล็อกสำหรับอินสแตนซ์ของคลาสที่กำหนดได้"
liwp

แก้ไขแล้ว. ฉันตั้งใจจะพูดอย่างนั้น
Thomas Jung

2
อินสแตนซ์คลาสเทียบกับอินสแตนซ์คืออะไร?
Weishi Zeng

ดังนั้นหากคุณมีวิธีการคงที่และเราไม่ต้องการซิงโครไนซ์ร่างกายทั้งหมดแสดงว่าเราซิงโครไนซ์ (สิ่งนี้) ไม่ดีซิงโครไนซ์ (Foo.class) แทนก็เหมาะสม นั่นถูกต้องใช่ไหม?
krupal.agile

84

หากต้องการเพิ่มคำตอบอื่น ๆ :

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

เทียบเท่ากับ

static synchronized void myMethod() {
  //code
}

และ

void myMethod() {
  synchronized(this) {
    //code
  }
}

เทียบเท่ากับ

synchronized void myMethod() {
  //code
}

12
ฉันใช้เวลาอ่านเป็นครั้งที่สองเพื่อให้ทราบว่าสองตัวอย่างแรกมีคำหลัก "คงที่" เพียงแค่ชี้ให้คนอื่น ๆ ได้เห็นสิ่งนี้และพลาดไป หากไม่มีคีย์เวิร์ดแบบคงที่สองตัวอย่างแรกจะไม่เหมือนกัน
kurtzbot

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

สาธารณะแบบคงที่ getInstance () {if (อินสแตนซ์ == null) {ซิงโครไนซ์ (Singleton.class) {อินสแตนซ์ = Singleton ใหม่ (); }} ส่งคืนอินสแตนซ์; }
JacksOnF1re

2
ประเด็นทั้งหมดคือไม่มีรหัสนอกsynchronizedบล็อก นั่นทำให้เทียบเท่า หากคุณเปลี่ยนตัวอย่างหนึ่งตัวอย่างก็จะไม่เหมือนเดิมอีกต่อไป
ก.ค.

23

ไม่อย่างแรกจะได้รับการล็อคนิยามคลาสMyClassไม่ใช่อินสแตนซ์ทั้งหมดของมัน อย่างไรก็ตามหากใช้ในอินสแตนซ์สิ่งนี้จะบล็อกอินสแตนซ์อื่น ๆ ทั้งหมดได้อย่างมีประสิทธิภาพเนื่องจากพวกเขาแชร์นิยามคลาสเดียว

อย่างที่สองจะได้รับการล็อคอินสแตนซ์ปัจจุบันเท่านั้น

ว่าสิ่งนี้ทำให้เธรดออบเจ็กต์ของคุณปลอดภัยหรือไม่นั่นเป็นคำถามที่ซับซ้อนมากขึ้น - เราต้องดูรหัสของคุณ!


1
ใช่ MyClass.class อาจเป็นตัวแปรคงที่และมีผลเหมือนกัน
pstanton

0

ใช่มันจะ (บนบล็อก / ฟังก์ชันที่ซิงโครไนซ์ใด ๆ )

ฉันสงสัยเกี่ยวกับคำถามนี้มาสองสามวันแล้วสำหรับตัวเอง (จริงๆแล้วใน kotlin) ในที่สุดฉันก็พบคำอธิบายที่ดีและต้องการแบ่งปัน:

การล็อกระดับคลาสป้องกันไม่ให้เธรดจำนวนมากเข้าสู่บล็อกที่ซิงโครไนซ์ในอินสแตนซ์ที่มีอยู่ทั้งหมดของคลาสบนรันไทม์ ซึ่งหมายความว่าหากในรันไทม์มี DemoClass 100 อินสแตนซ์จะมีเพียงเธรดเดียวเท่านั้นที่สามารถรัน demoMethod () ในอินสแตนซ์ใดอินสแตนซ์ใดก็ได้ในแต่ละครั้งและอินสแตนซ์อื่น ๆ ทั้งหมดจะถูกล็อกสำหรับเธรดอื่น

ควรทำการล็อกระดับคลาสเพื่อให้เธรดข้อมูลคงที่ปลอดภัย ดังที่เราทราบว่าคำสำคัญแบบคงที่เชื่อมโยงข้อมูลของวิธีการกับระดับชั้นเรียนดังนั้นให้ใช้การล็อกที่เขตข้อมูลคงที่หรือวิธีการเพื่อให้อยู่ในระดับชั้นเรียน

นอกจากนี้ยังสังเกตเห็นว่าทำไม. class . เป็นเพียงเพราะ.classเทียบเท่ากับตัวแปรคงที่ของคลาสที่คล้ายกับ:

private final static Object lock = new Object();

โดยที่ชื่อตัวแปรล็อคคือคลาสและประเภทคือคลาส <T>

อ่านเพิ่มเติม: https://howtodoinjava.com/java/multi-threading/object-vs-class-level-locking/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.