การประสานเทียบกับล็อค


182

java.util.concurrentAPI จัดให้มีคลาสที่เรียกว่าLockซึ่งโดยทั่วไปจะเรียงลำดับการควบคุมเพื่อเข้าถึงทรัพยากรที่สำคัญ มันทำให้วิธีการดังกล่าวเป็นและ park()unpark()

เราสามารถทำสิ่งที่คล้ายกันถ้าเราสามารถใช้synchronizedคำหลักและการใช้wait()และnotify() notifyAll()วิธีการ

ฉันสงสัยว่าหนึ่งในสิ่งเหล่านี้ดีกว่าในการปฏิบัติและทำไม?


1
บทความที่เป็นประโยชน์ที่นี่: javarevisited.blogspot.in/2013/03/…
roottraveller

คำตอบ:


178

หากคุณเพียงแค่ล็อควัตถุฉันต้องการใช้ synchronized

ตัวอย่าง:

Lock.acquire();
doSomethingNifty(); // Throws a NPE!
Lock.release(); // Oh noes, we never release the lock!

คุณต้องทำtry{} finally{}ทุกที่อย่างชัดเจน

ในขณะที่มีการซิงโครไนส์มันชัดเจนและเป็นไปไม่ได้ที่จะผิด:

synchronized(myObject) {
    doSomethingNifty();
}

ที่กล่าวว่าLocks อาจมีประโยชน์มากขึ้นสำหรับสิ่งที่ซับซ้อนมากขึ้นซึ่งคุณไม่สามารถหาและเผยแพร่ได้ในลักษณะที่สะอาด ฉันต้องการหลีกเลี่ยงการใช้งานLocks เปล่าโดยสุจริตและเริ่มต้นด้วยการควบคุมภาวะพร้อมกันที่ซับซ้อนยิ่งขึ้นเช่น a CyclicBarrierหรือ a LinkedBlockingQueueหากพวกเขาตอบสนองความต้องการของคุณ

ฉันไม่เคยมีเหตุผลที่จะใช้wait()หรือnotify()อาจมีบางอย่างที่ดี


1
ความแตกต่างระหว่างการรอ / แจ้งเตือนกับ park / unpark ของ LockSupport คืออะไร docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/…
Pacerier

6
ในตอนแรกตัวอย่างมีเหตุผลกับล็อค แต่แล้วฉันก็รู้ว่าถ้าคุณใช้ลองในที่สุดบล็อกปัญหานั้นจะหลีกเลี่ยงได้โดยล็อคไม่ได้รับการปล่อยตัว
William Reed

อ๊ะ ... หนึ่งในช่วงเวลานั้นที่ได้ชื่นชมแบบของ RAII ใน C ++ std::lock_guard
WhiZTiM

67

ฉันสงสัยว่าหนึ่งในสิ่งเหล่านี้ดีกว่าในการปฏิบัติและทำไม?

ฉันพบว่าLockและCondition(และconcurrentคลาสใหม่อื่น ๆ) เป็นเพียงเครื่องมือเพิ่มเติมสำหรับกล่องเครื่องมือ ฉันสามารถทำทุกสิ่งที่ฉันต้องการได้มากที่สุดด้วยค้อนก้ามปูตัวเก่า ( synchronizedคำหลัก) แต่มันก็แปลกที่จะใช้ในบางสถานการณ์ สถานการณ์ที่น่าอึดอัดใจหลายอย่างกลายเป็นเรื่องง่ายขึ้นมากเมื่อฉันเพิ่มเครื่องมือเพิ่มเติมลงในกล่องเครื่องมือของฉัน: ค้อนยาง, ค้อนทุบลูก, ก้านเหล็กและตะปูตอก อย่างไรก็ตามค้อนเล็บเก่าของฉันยังคงเห็นการใช้งานร่วมกัน

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

===

ฉันคิดว่าJavaDocทำงานได้ดีในการอธิบายความแตกต่างระหว่างLockและsynchronized(เน้นเป็นของฉัน):

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

...

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

ในขณะที่กลไกการกำหนดขอบเขตสำหรับวิธีการและคำสั่งที่ซิงโครไนซ์ทำให้การโปรแกรมด้วยการล็อกหน้าจอง่ายขึ้นและช่วยหลีกเลี่ยงข้อผิดพลาดทั่วไปของการเขียนโปรแกรมที่เกี่ยวข้องกับการล็อกมีหลายครั้งที่คุณจำเป็นต้องทำงานกับการล็อก ตัวอย่างเช่น * * อัลกอริธึมบางอย่าง *สำหรับการสำรวจโครงสร้างข้อมูลที่เข้าถึงพร้อมกันจำเป็นต้องใช้ "hand-over-hand" หรือ "chain lock" : คุณได้รับการล็อคของโหนด A จากนั้นโหนด B จากนั้นปล่อย A และรับ C จากนั้นปล่อย B และรับ D และอื่น ๆ การนำไปใช้งานของส่วนต่อประสานการล็อคช่วยให้สามารถใช้เทคนิคดังกล่าวได้โดยการอนุญาตให้ทำการล็อกและปลดล็อคในขอบเขตที่แตกต่างกันและช่วยให้หลายล็อคที่จะได้มาและปล่อยออกมาในลำดับใด

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

...

เมื่อล็อคและปลดล็อคเกิดขึ้นในขอบเขตที่แตกต่างกันจะต้องระมัดระวังเพื่อให้แน่ใจว่ารหัสทั้งหมดที่ถูกดำเนินการในขณะที่ล็อคจะถูกป้องกันโดยลองในที่สุดหรือลองจับเพื่อให้แน่ใจว่าการปลดล็อคเมื่อมีความจำเป็น

การใช้งานล็อคให้ฟังก์ชันการทำงานเพิ่มเติมมากกว่าการใช้วิธีการทำข้อมูลให้ตรงกันและงบโดยการให้ความพยายามที่ไม่ปิดกั้นที่จะได้รับล็อค (tryLock ()), ความพยายามที่จะได้รับล็อคที่สามารถขัดจังหวะ (lockInterruptibly () และความพยายามกับผู้ซื้อ ล็อคที่สามารถหมดเวลา (ลองล็อค (ยาว, TimeUnit))

...


23

คุณสามารถบรรลุทุกอย่างสาธารณูปโภคในjava.util.concurrent ทำอย่างไรกับวิทยาการระดับต่ำเช่นsynchronized, volatileหรือรอ / แจ้ง

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

API ที่เกิดขึ้นพร้อมกันนั้นให้แนวทางระดับสูงกว่าซึ่งง่ายกว่า (และปลอดภัยกว่า) ในการใช้ สรุปคุณไม่ควรใช้synchronized, volatile, wait, notifyโดยตรงอีกต่อไป

ล็อค ระดับตัวเองเป็นทางด้านระดับล่างของกล่องนี้คุณอาจไม่จำเป็นต้องแม้จะใช้ที่โดยตรงอย่างใดอย่างหนึ่ง (คุณสามารถใช้Queuesและสัญญาณและสิ่งอื่น ๆ ส่วนใหญ่ของเวลา)


2
การรอ / แจ้งเตือนแบบเก่าธรรมดาถือว่าเป็นระบบดั้งเดิมในระดับที่ต่ำกว่า java.util.concurrent.locks.LockSupport's park / unpark หรือเป็นวิธีอื่น ๆ หรือไม่
Pacerier

@Pierier: ฉันคิดว่าทั้งสองเป็นระดับต่ำ (เช่นสิ่งที่โปรแกรมเมอร์แอปพลิเคชันต้องการหลีกเลี่ยงการใช้โดยตรง) แต่แน่นอนส่วนล่างของ java.util.concurrency (เช่นแพ็คเกจล็อค) ถูกสร้างขึ้นที่ด้านบน ของดั้งเดิม JVM ดั้งเดิมรอ / แจ้ง (ซึ่งเป็นระดับที่ต่ำกว่า)
Thilo

2
ไม่ฉันหมายถึงจาก 3: Thread.sleep / interrupt, Object.wait / แจ้งเตือน, LockSupport.park / unpark ซึ่งดั้งเดิมที่สุด ?
Pacerier

2
@Thilo ฉันไม่แน่ใจว่าวิธีที่คุณสนับสนุนคำสั่งของคุณที่java.util.concurrentง่ายกว่า [ทั่วไป] คุณสมบัติภาษา ( synchronizedฯลฯ ... ) เมื่อคุณใช้java.util.concurrentคุณต้องสร้างนิสัยให้เสร็จlock.lock(); try { ... } finally { lock.unlock() }ก่อนที่จะเขียนโค้ดในขณะที่synchronizedคุณเป็นคนดีตั้งแต่เริ่มต้น บนพื้นฐานนี้คนเดียวผมจะบอกว่าsynchronizedเป็นเรื่องง่าย (ให้คุณต้องการพฤติกรรมของมัน) java.util.concurrent.locks.Lockมากกว่า พาร์ 4
Iwan Aucamp

1
อย่าคิดว่าคุณสามารถจำลองการทำงานของคลาส AtomicXXX ได้อย่างแน่นอนด้วยการทำงานแบบพร้อมกันเนื่องจากพวกเขาใช้การเรียกใช้ CAS ดั้งเดิมที่ไม่มีใน java.util.concurrent ก่อนหน้านี้
Duncan Armstrong

15

มี 4 ปัจจัยหลักที่ว่าทำไมคุณต้องการที่จะใช้หรือsynchronizedjava.util.concurrent.Lock

หมายเหตุ: การล็อคแบบซิงโครไนซ์คือสิ่งที่ฉันหมายถึงเมื่อฉันพูดว่าการล็อคที่แท้จริง

  1. เมื่อ Java 5 ออกมาพร้อมกับ ReentrantLocks พวกเขาพิสูจน์แล้วว่ามีความแตกต่างของปริมาณงานที่เห็นได้ชัดเจนจากนั้นจึงทำการล็อคที่แท้จริง หากคุณกำลังมองหากลไกการล็อคที่เร็วขึ้นและใช้งาน 1.5 ให้พิจารณา jucReentrantLock การล็อคที่แท้จริงของ Java 6 นั้นเทียบได้แล้ว

  2. jucLock มีกลไกที่แตกต่างกันสำหรับการล็อค ล็อคขัดจังหวะ - พยายามล็อคจนกว่าด้ายล็อคถูกขัดจังหวะ หมดเวลาล็อค - พยายามล็อคตามระยะเวลาและยกเลิกหากคุณไม่ประสบความสำเร็จ tryLock - พยายามล็อคถ้ามีเธรดอื่นค้างไว้ให้ล็อค ทั้งหมดนี้รวมอยู่นอกเหนือจากล็อคง่าย ๆ การล็อคภายในมีการล็อคอย่างง่ายเท่านั้น

  3. สไตล์ หากทั้ง 1 และ 2 ไม่ได้อยู่ในหมวดหมู่ของสิ่งที่คุณเกี่ยวข้องกับคนส่วนใหญ่รวมถึงตัวฉันเองจะพบว่าเซมินาติคล็อคภายในนั้นอ่านง่ายขึ้นและ verbose น้อยลงแล้วล็อค jucLock
  4. หลายเงื่อนไข วัตถุที่คุณล็อคสามารถแจ้งเตือนและรอได้ในกรณีเดียว วิธี newCondition ของ Lock อนุญาตให้ Lock เดียวมีเหตุผลหลายอย่างที่จะรอหรือส่งสัญญาณ ฉันยังไม่ได้ต้องการฟังก์ชั่นนี้ในทางปฏิบัติ แต่เป็นคุณสมบัติที่ดีสำหรับผู้ที่ต้องการมัน

ฉันชอบรายละเอียดเกี่ยวกับความคิดเห็นของคุณ ฉันจะเพิ่มสัญลักษณ์แสดงหัวข้อย่อยอีกหนึ่ง - ReadWriteLock ให้พฤติกรรมที่มีประโยชน์หากคุณกำลังจัดการกับหลายหัวข้อเท่านั้นบางแห่งที่ต้องเขียนไปยังวัตถุ หลายเธรดสามารถอ่านวัตถุพร้อมกันและถูกบล็อกเฉพาะเมื่อเธรดอื่นกำลังเขียนลงไป
Sam Goldberg

5

ฉันต้องการเพิ่มบางสิ่งเพิ่มเติมบนคำตอบของ Bert F

Locksรองรับวิธีการต่าง ๆ สำหรับการควบคุมการล็อกที่ละเอียดยิ่งขึ้นซึ่งมีความหมายมากกว่าจอภาพโดยปริยาย ( synchronizedล็อค)

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

ข้อดีของการล็อคการประสานข้อมูลจากหน้าเอกสาร

  1. การใช้วิธีการหรือข้อความสั่งแบบซิงโครไนซ์ให้การเข้าถึงการล็อกการมอนิเตอร์โดยนัยที่เกี่ยวข้องกับทุกวัตถุ แต่บังคับให้การล็อกและการปล่อยล็อกทั้งหมดเกิดขึ้นในลักษณะที่มีโครงสร้างแบบบล็อก

  2. การใช้งานล็อคให้การทำงานเพิ่มเติมมากกว่าการใช้วิธีการทำข้อมูลให้ตรงกันและงบโดยการให้ความพยายามที่ไม่ปิดกั้นที่จะได้รับlock (tryLock())เป็นความพยายามที่จะได้รับล็อคที่สามารถขัดจังหวะ ( และความพยายามที่จะได้รับล็อคที่กระป๋องlockInterruptibly()timeout (tryLock(long, TimeUnit))

  3. คลาสล็อคยังสามารถให้ลักษณะการทำงานและความหมายที่ค่อนข้างแตกต่างจากที่ล็อคหน้าจอโดยปริยายเช่นการสั่งซื้อรับประกันการใช้งานที่ไม่ใช่ reentrant หรือการตรวจสอบการหยุดชะงัก

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

ReentrantLockคุณสมบัติที่สำคัญตามบทความนี้

  1. ความสามารถในการล็อคอินเตอร์รัปต์
  2. ความสามารถในการหมดเวลาในขณะที่รอการล็อค
  3. พลังในการสร้างการล็อคที่ยุติธรรม
  4. API เพื่อรับรายการเธรดที่รอการล็อก
  5. ความยืดหยุ่นในการลองล็อคโดยไม่ปิดกั้น

คุณสามารถใช้ ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLockเพื่อรับการควบคุมเพิ่มเติมเกี่ยวกับการล็อคแบบละเอียดในการอ่านและเขียน

นอกจาก ReentrantLocks ทั้งสามนี้แล้ว Java 8 ยังมี Lock อีกหนึ่งตัว

StampedLock:

Java 8 มาพร้อมกับล็อคแบบใหม่ที่เรียกว่า StampedLock ซึ่งรองรับการล็อกการอ่านและการเขียนเช่นเดียวกับในตัวอย่างด้านบน ตรงกันข้ามกับ ReadWriteLock วิธีการล็อคของ StampedLock ส่งคืนตราประทับที่แสดงด้วยค่ายาว

คุณสามารถใช้ตราประทับเหล่านี้เพื่อปลดล็อคหรือตรวจสอบว่าล็อคยังใช้งานได้อยู่หรือไม่ นอกจากนี้ล็อคที่ประทับตรายังรองรับโหมดล็อคอื่นที่เรียกว่าการล็อคในแง่ดี

ดูที่บทความนี้เกี่ยวกับการใช้งานประเภทReentrantLockและStampedLockล็อคที่แตกต่างกัน


4

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

synchronized(foo) {
}

หรือ

lock.acquire(); .....lock.release();

ไม่รับประกันความยุติธรรม

หากคุณมีข้อโต้แย้งมากมายเกี่ยวกับการล็อคคุณสามารถเผชิญหน้ากับการต่อรองราคาที่คำขอที่ใหม่กว่าได้รับการล็อคและคำขอที่เก่ากว่าติดอยู่ ฉันเคยเห็นกรณีที่มี 200 กระทู้มาถึงในระยะเวลาอันสั้นสำหรับการล็อคและอันที่ 2 ที่จะมาถึงได้รับการดำเนินการครั้งสุดท้าย สิ่งนี้ใช้ได้สำหรับบางแอปพลิเคชั่น แต่สำหรับคนอื่นมันก็เป็นอันตราย

ดูหนังสือ "Java Concurrency In Practice" ของ Brian Goetz ในหัวข้อ 13.3 สำหรับการสนทนาแบบเต็มของหัวข้อนี้


5
"การซิงโครไนซ์ระดับวิธีทำให้มั่นใจได้ว่าการจัดสรรล็อคแบบยุติธรรมหรือแบบ FIFO" => จริงเหรอ? คุณกำลังบอกว่าวิธีการซิงโครไนซ์มีพฤติกรรมแตกต่างจากความยุติธรรมมากกว่าการห่อเนื้อหาของวิธีการลงในบล็อก {} ที่ซิงโครไนซ์หรือไม่? ฉันจะไม่คิดอย่างนั้นหรือฉันเข้าใจประโยคนั้นผิด ...
weiresr

ใช่แม้ว่าจะแปลกใจและตอบโต้ได้ง่าย หนังสือของ Goetz เป็นคำอธิบายที่ดีที่สุด
Brian Tarbox

หากคุณดูรหัสที่ @BrianTarbox ให้บล็อกการซิงโครไนซ์กำลังใช้วัตถุอื่นนอกเหนือจาก "นี่" เพื่อล็อค ในทางทฤษฎีไม่มีความแตกต่างระหว่างวิธีการซิงโครไนซ์และวางทั้งร่างของวิธีการที่กล่าวไว้ในบล็อกที่ซิงโครไนซ์ตราบใดที่บล็อกใช้ "this" เป็นการล็อค
xburgos

คำตอบควรได้รับการแก้ไขเพื่อรวมการเสนอราคาและทำให้ชัดเจนว่า "การรับรอง" ที่นี่คือ "การรับประกันเชิงสถิติ" ไม่ใช่การกำหนดที่แน่นอน
Nathan Hughes

ขออภัยฉันเพิ่งค้นพบว่าฉันลงคะแนนผิดคำตอบนี้เมื่อไม่กี่วันที่ผ่านมา (การคลิกที่เงอะงะ) น่าเสียดายที่ในปัจจุบันดังนั้นฉันจะไม่ยอมคืน หวังว่าฉันจะแก้ไขได้ในภายหลัง
Mikko Östlund

3

หนังสือ "Java Concurrency In Practice" ของ Brian Goetz, มาตรา 13.3: "... เช่นเดียวกับ ReentrantLock ที่เป็นค่าเริ่มต้นการล็อกที่แท้จริงไม่ได้รับประกันความเป็นธรรมที่กำหนดขึ้น แต่การรับประกันความเป็นธรรมทางสถิติของการติดตั้งส่วนใหญ่นั้น


2

ล็อคทำให้ชีวิตโปรแกรมเมอร์ง่ายขึ้น นี่คือบางสถานการณ์ที่สามารถทำได้อย่างง่ายดายด้วยการล็อก

  1. ล็อคในวิธีหนึ่งและปลดล็อคในวิธีอื่น
  2. หากคุณมีสองเธรดที่ทำงานกับโค้ดสองส่วนที่แตกต่างกันอย่างไรก็ตามในเธรดแรกมีสิ่งที่จำเป็นต้องมีล่วงหน้าบนโค้ดบางส่วนในเธรดที่สอง (ในขณะที่เธรดอื่น ๆ บางตัวยังทำงานบนโค้ดเดียวกันในวินาที ด้ายพร้อมกัน) การล็อคที่ใช้ร่วมกันสามารถแก้ปัญหานี้ได้ค่อนข้างง่าย
  3. การใช้งานจอภาพ ตัวอย่างเช่นคิวอย่างง่าย ๆ ที่วิธีการรับและวางถูกดำเนินการจากเธรดอื่น ๆ อย่างไรก็ตามคุณไม่ต้องการให้หลายวิธี (หรือรับ) วิธีการทำงานพร้อมกันไม่ว่าวิธีการได้รับและเรียกใช้พร้อมกัน ล็อคส่วนตัวทำให้ชีวิตของคุณง่ายขึ้น

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


1

ความแตกต่างที่สำคัญระหว่างการล็อคและการซิงโครไนซ์:

  • ด้วยการล็อคคุณสามารถปลดล็อคและรับการล็อคในลำดับใดก็ได้
  • ด้วยการซิงโครไนซ์คุณสามารถปลดล็อคเฉพาะในลำดับที่ได้มา

0

ล็อคและประสานบล็อกทั้งสองมีวัตถุประสงค์เดียวกัน แต่ขึ้นอยู่กับการใช้งาน พิจารณาส่วนด้านล่าง

void randomFunction(){
.
.
.
synchronize(this){
//do some functionality
}

.
.
.
synchronize(this)
{
// do some functionality
}


} // end of randomFunction

ในกรณีข้างต้นหากเธรดเข้าสู่บล็อกซิงโครไนซ์บล็อกอื่นจะถูกล็อคเช่นกัน หากมีบล็อกซิงโครไนซ์หลายตัวบนวัตถุเดียวกันบล็อกทั้งหมดจะถูกล็อค ในสถานการณ์เช่นนี้สามารถใช้ java.util.concurrent.Lock เพื่อป้องกันการล็อคบล็อกที่ไม่พึงประสงค์

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