บทความนี้ส่วนใหญ่ศึกษาเนื้อหาทั้งหมดของล็อคในแง่ร้ายและล็อคในแง่ดีตามรายละเอียดด้านล่าง
การล็อคในแง่ร้ายมักจะใช้โดยกลไกฐานข้อมูล ในระหว่างกระบวนการทั้งหมดข้อมูลจะถูกล็อค (เมื่อสอบถาม) ตราบใดที่สิ่งต่าง ๆ ไม่ได้เปิดตัว (commit/ย้อนกลับ) ผู้ใช้จะไม่สามารถดูหรือแก้ไขได้
มาอธิบายผ่านกรณีด้านล่าง
กรณี: สมมติว่าสินค้าคงคลังของสินค้าคือ 1,000 และเมื่อนักบัญชี 1 นำข้อมูลออกมาและเตรียมพร้อมสำหรับการปรับเปลี่ยน แต่มีบางอย่างชั่วคราวเขาออกไป ในช่วงเวลานี้การบัญชี 2 สกัดข้อมูลและลบปริมาณโดย 200 จากนั้นบัญชี 1 กลับมาและลบปริมาณที่เพิ่งลบออก 200 ซึ่งทำให้เกิดปัญหา การบัญชี 1 ไม่ได้ทำการปรับเปลี่ยนใด ๆ ตาม 800 ซึ่งเรียกว่าการสูญเสียการอัปเดตและสามารถแก้ไขได้โดยใช้ล็อคในแง่ร้าย
สินค้าคงคลัง Java:
สินค้าคงคลังคลาสสาธารณะ { /* หมายเลขสินค้าคงคลัง* / สตริงส่วนตัว itemno; /* ชื่อสินค้าคงคลัง*/ itemname สตริงส่วนตัว; /* ปริมาณสินค้าคงคลัง*/ ปริมาณ int ส่วนตัว; // ละเว้นวิธีการ setter และ getter}Inventory.hbm.xml:
<? xml version = "1.0"?> <! doctype hibernate-mapping สาธารณะ "-// hibernate/hibernate mapping dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" table = "t_inventory"> <!-การกำหนดด้วยตนเองของคีย์หลัก-> <id name = "itemno"> <generator // id> <!-คุณสมบัติการแมป-> <property name = "itemName"/> <property name = "ปริมาณ"/>
คลาสทดสอบ:
นักบัญชี 1 โหลดข้อมูลผ่านการล็อคในแง่ร้ายและปรับเปลี่ยนข้อมูล!
โมฆะสาธารณะ testload1 () {เซสชันเซสชัน = null; ลอง {session = hibernateutils.getSession (); session.beginTransaction (); /*มีการเพิ่มการล็อคในแง่ร้ายเมื่อโหลดทำให้ผู้ใช้รายอื่นไม่สามารถเข้าถึง*/ สินค้าคงคลัง Inv = (สินค้าคงคลัง) เซสชันโหลด (Inventory.class, "1001", lockmode.upgrade); /*รับข้อมูล*/ system.out.println ("opt1-> itemno =" + inv.getItemno ()); System.out.println ("opt1-> itemname =" + inv.getItemname ()); System.out.println ("opt1-> quantity =" + inv.getQuantity ()); /*ปริมาณลบ 200*/ inv.SetQuantity (inv.getQuantity () - 200); session.getTransaction (). commit (); } catch (exception e) {e.printstacktrace (); session.getTransaction (). ย้อนกลับ (); } ในที่สุด {hibernateutils.closesession (เซสชัน); -นักบัญชี 2 และนักบัญชี 1 มีการดำเนินการเดียวกันและทั้งสองแก้ไขข้อมูลในฐานข้อมูล!
โมฆะสาธารณะ testload2 () {เซสชันเซสชัน = null; ลอง {session = hibernateutils.getSession (); session.beginTransaction (); /*เพิ่มการล็อคเมื่อโหลดข้อมูลเพื่อให้ผู้อื่นไม่สามารถรับข้อมูล*/ Inventory Inv = (Inventory) Session.load (Inventory.class, "1001", lockmode.upgrade); /*รับข้อมูลจริง*/ system.out.println ("opt2-> itemno =" + inv.getItemno ()); System.out.println ("opt2-> itemname =" + inv.getItemname ()); System.out.println ("opt2-> quantity =" + inv.getQuantity ()); /*สินค้าคงคลังลบ 200*/ inv.SetQuantity (inv.getQuantity () - 200); session.getTransaction (). commit (); } catch (exception e) {e.printstacktrace (); session.getTransaction (). ย้อนกลับ (); } ในที่สุด {hibernateutils.closesession (เซสชัน); -หมายเหตุ: การดำเนินการที่ดำเนินการโดยนักบัญชีสองคนนั้นเหมือนกัน หากมีการเพิ่มการล็อคในแง่ร้ายนักบัญชีจะนำข้อมูลและแก้ไขข้อมูล ก่อนที่นักบัญชี 1 จะส่งสิ่งนั้นนักบัญชี 2 ไม่สามารถเข้าถึงข้อมูลและสามารถอยู่ในสถานะรอได้เท่านั้น หลังจากรู้ว่านักบัญชี 1 ได้ส่งสิ่งนั้นแล้ว Accountant 2 มีโอกาสทำงานกับข้อมูลในฐานข้อมูล
ผ่านกรณีล็อคในแง่ร้ายข้างต้นเราสามารถพบได้ว่าข้อได้เปรียบที่ใหญ่ที่สุดของการล็อคในแง่ร้ายคือมันสามารถป้องกันการสูญเสียการอัปเดต เมื่อเครื่องคิดเลข 1 กำลังประมวลผลข้อมูลเครื่องคิดเลข 2 สามารถอยู่ในสถานะรอได้เท่านั้น หลังจากเครื่องคิดเลข 1 ส่งสิ่งนี้เครื่องคิดเลข 2 มีโอกาสแก้ไขข้อมูล แต่ก็มีปัญหาใหญ่นั่นคือถ้านักบัญชี 1 สอบถามข้อมูลและใบแล้วคนอื่น ๆ จะต้องรอเกือบตลอดทั้งวันซึ่งเสียเวลามาก เพื่อแก้ปัญหานี้เราสามารถใช้ล็อคในแง่ดี
การล็อคในแง่ดีไม่ใช่ล็อคในความหมายที่แท้จริง ในกรณีส่วนใหญ่พวกเขาจะถูกนำไปใช้ในรูปแบบของเวอร์ชันข้อมูล โดยทั่วไปฟิลด์เวอร์ชันจะถูกเพิ่มลงในฐานข้อมูลและเวอร์ชันจะถูกอ่านออกเมื่ออ่านข้อมูล เมื่อบันทึกข้อมูลจะกำหนดว่าค่าเวอร์ชันนั้นเล็กกว่าค่าเวอร์ชันของฐานข้อมูลหรือไม่ หากน้อยกว่านั้นจะไม่ได้รับการอัปเดตมิฉะนั้นจะได้รับการอัปเดต
การตั้งค่า Javabean ภายใต้การล็อคในแง่ดี, Inventory.java:
สินค้าคงคลังคลาสสาธารณะ { /*หมายเลขสินค้าคงคลัง* / สตริงส่วนตัว itemno; /*ชื่อสินค้าคงคลัง*/ itemname สตริงส่วนตัว; /*ปริมาณสินค้าคงคลัง*/ ปริมาณ int ส่วนตัว; /*เวอร์ชันข้อมูล*/ เวอร์ชัน INT ส่วนตัว; // ละเว้นวิธีการ setter และ getter}Inventory.hbm.xml:
<? xml version = "1.0"?> <! doctype hibernate-mapping สาธารณะ "-// hibernate/hibernate mapping dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ความเชื่อมั่น-> <class name = "com.lixue.bean.inventory" ตาราง = "t_inventory" optimistic-lock = "เวอร์ชัน"> <!-การแมปคีย์หลัก-> <id name = "itemno"> <generator/> </id> <! <property name = "ปริมาณ"/> </class> </hibernate-mapping>
หมายเหตุ: ไฟล์การแมปโดยใช้การล็อคในแง่ดีกำหนดว่าการแมปของฟิลด์เวอร์ชันจะต้องแมปก่อนหลังจากรหัสคีย์หลัก
นักบัญชี 1 ประมวลผลข้อมูลในสถานการณ์การล็อคในแง่ดี:
โมฆะสาธารณะ testload1 () {เซสชันเซสชัน = null; ลอง {session = hibernateutils.getSession (); session.beginTransaction (); /*โหลดข้อมูลภายใต้การล็อคในแง่ดี*/ สินค้าคงคลัง Inv = (สินค้าคงคลัง) เซสชันโหลด (Inventory.class, "1001"); /*การเก็บข้อมูลจริง*/ system.out.println ("opt1-> itemno =" + inv.getItemno ()); System.out.println ("opt1-> itemname =" + inv.getItemname ()); System.out.println ("opt1-> version =" + inv.getVersion ()); System.out.println ("opt1-> quantity =" + inv.getQuantity ()); /*ปริมาณลบ 200*/ inv.SetQuantity (inv.getQuantity () - 200); session.getTransaction (). commit (); } catch (exception e) {e.printstacktrace (); session.getTransaction (). ย้อนกลับ (); } ในที่สุด {hibernateutils.closesession (เซสชัน); -บัญชี 2 ประมวลผลข้อมูลภายใต้การล็อคในแง่ดี (นักบัญชี 2 สามารถประมวลผลข้อมูลได้โดยไม่ต้องส่ง)
โมฆะสาธารณะ testload2 () {เซสชันเซสชัน = null; ลอง {session = hibernateutils.getSession (); session.beginTransaction (); /*โหลดข้อมูลภายใต้การล็อคในแง่ดี*/ สินค้าคงคลัง Inv = (สินค้าคงคลัง) เซสชันโหลด (Inventory.class, "1001"); /*การเก็บข้อมูลจริง*/ system.out.println ("opt2-> itemno =" + inv.getItemno ()); System.out.println ("opt2-> itemname =" + inv.getItemname ()); System.out.println ("opt2-> version =" + inv.getVersion ()); System.out.println ("opt2-> quantity =" + inv.getQuantity ()); /*ปริมาณลบ 200*/ inv.SetQuantity (inv.getQuantity () - 200); session.getTransaction (). commit (); } catch (exception e) {e.printstacktrace (); session.getTransaction (). ย้อนกลับ (); } ในที่สุด {hibernateutils.closesession (เซสชัน); -หมายเหตุ: ในสถานที่ที่นักบัญชีจะนำข้อมูลและลบหมายเลขด้วย 200 และไม่ส่งนักบัญชี 2 ยังสามารถใช้งานข้อมูลได้ สิ่งนี้แตกต่างจากล็อคในแง่ร้าย เมื่อบัญชี 2 ดำเนินการข้อมูลและส่งเวอร์ชันเวอร์ชันข้อมูลในฐานข้อมูลจะถูกเพิ่มโดย 1 จากนั้นเมื่อบัญชี 1 กลับมาส่งสิ่งที่ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้นว่าข้อมูลได้รับการอัปเดตแล้วโหลดใหม่
ล็อคในแง่ร้ายจะส่งผลกระทบต่อการเกิดขึ้นพร้อมกันสูงดังนั้นจึงเป็นการดีกว่าที่จะใช้ล็อคในแง่ดี
ข้างต้นเป็นคำอธิบายโดยละเอียดทั้งหมดของการล็อคในแง่ร้ายและตัวอย่างล็อคในแง่ดีในบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!