1. Longadder
มันถูกใช้ในลักษณะเดียวกันกับ atomiclong แต่มีประสิทธิภาพที่ดีกว่า atomiclong
Longadder และ Atomiclong ใช้การดำเนินการอะตอมเพื่อปรับปรุงประสิทธิภาพ อย่างไรก็ตาม Longadder ทำการแยกฮอตสปอตตาม Atomiclong การแยกฮอตสปอตคล้ายกับการลดขนาดอนุภาคล็อคในการทำงานที่ล็อคโดยแยกล็อคออกเป็นล็อคหลายตัวเพื่อปรับปรุงประสิทธิภาพ ในการล็อคฟรีวิธีที่คล้ายกันสามารถใช้เพื่อเพิ่มอัตราความสำเร็จของ CAS ซึ่งจะช่วยปรับปรุงประสิทธิภาพ
แผนผัง Longadder:
วิธีการใช้งานของ atomiclong คือมีตัวแปรค่าอยู่ภายใน เมื่อหลายเธรดมีการเพิ่มขึ้นของตัวเองและลดขนาดตัวเองพวกเขาทั้งหมดจะดำเนินการจากระดับการเรียนการสอนของเครื่องผ่านคำแนะนำ CAS เพื่อให้แน่ใจว่าอะตอมของการเกิดขึ้นพร้อมกัน เหตุผลเดียวที่ จำกัด ประสิทธิภาพของ Atomiclong คือการเกิดขึ้นพร้อมกันสูง การเกิดขึ้นพร้อมกันสูงหมายความว่า CAS มีโอกาสสูงกว่าของความล้มเหลวเวลาลองอีกครั้งมากขึ้นและยิ่งมีการลองอีกครั้งมากขึ้นโอกาสที่จะเกิดความล้มเหลวของ CAS ซึ่งจะกลายเป็นวงจรอุบาทว์และประสิทธิภาพของอะตอมมิกก็ลดลง
Longadder จะแบ่งค่าออกเป็นหลายเซลล์และเพิ่มเซลล์ทั้งหมดเข้ากับค่า ดังนั้นเมื่อเพิ่มและลบ longadder คุณจะต้องทำงานกับเซลล์ที่แตกต่างกันเท่านั้น เธรดที่แตกต่างกันดำเนินการ CAS ในเซลล์ที่แตกต่างกัน แน่นอนว่าอัตราความสำเร็จของ CAS สูง (ลองนึกภาพ 3+2+1 = 6, หนึ่งเธรด 3+1, เธรดอื่น ๆ 2+1 และในที่สุด 8 Longadder ไม่มี API สำหรับการคูณและการแบ่ง)
อย่างไรก็ตามเมื่อหมายเลขพร้อมกันไม่สูงมากการแยกเป็นหลายเซลล์ก็ต้องมีการบำรุงรักษาเซลล์และการรวมซึ่งไม่ได้มีประสิทธิภาพเท่ากับการใช้งานของ Atomiclong Longadder ใช้วิธีที่ฉลาดในการแก้ปัญหานี้
ในสถานการณ์เริ่มต้น longadder และ atomiclong เหมือนกัน เฉพาะเมื่อ CA ล้มเหลวค่าจะถูกแบ่งออกเป็นเซลล์ ทุกครั้งที่เกิดความล้มเหลวจำนวนเซลล์จะเพิ่มขึ้น สิ่งนี้ยังมีประสิทธิภาพในการพร้อมกันต่ำ ในการพร้อมกันสูงวิธีการประมวลผล "ปรับตัว" นี้จะไม่ล้มเหลวหลังจากไปถึงเซลล์จำนวนหนึ่งและประสิทธิภาพจะได้รับการปรับปรุงอย่างมาก
Longadder เป็นกลยุทธ์ในการแลกเปลี่ยนพื้นที่สำหรับเวลา
2. สมบูรณ์
ใช้อินเทอร์เฟซ PrectiveStage (มากกว่า 40 วิธี) ซึ่งส่วนใหญ่ใช้ในการเขียนโปรแกรมฟังก์ชั่น และสนับสนุนการโทรสตรีมมิ่ง
PomptextFuture เป็นรุ่นที่ปรับปรุงแล้วใน Java 8
การใช้งานอย่างง่าย:
นำเข้า java.util.concurrent.completableFuture; คลาสสาธารณะ AskThread ดำเนินการ runnable {prectiableFuture <integer> re = null; Public AskThread (PrectiveFuture <Integer> re) {this.re = re; } @Override โมฆะสาธารณะ Run () {int myRe = 0; ลอง {myre = re.get () * re.get (); } catch (exception e) {} system.out.println (myre); } โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException {Final CompletableFuture <Integer> Future = ใหม่ PrectiableFuture <Integer> (); กระทู้ใหม่ (ใหม่ Askthread (อนาคต)). เริ่ม (); // จำลองหัวข้อการคำนวณระยะยาว sleep (1,000); // แจ้งผลลัพธ์ที่เสร็จสมบูรณ์ในอนาคต pplete (60); - สิ่งที่วิพากษ์วิจารณ์มากที่สุดเกี่ยวกับอนาคตคือคุณต้องรอและตรวจสอบว่างานเสร็จสมบูรณ์หรือไม่ ในอนาคตเวลาสำหรับงานที่จะเสร็จสมบูรณ์นั้นไม่สามารถควบคุมได้ การปรับปรุงที่ยิ่งใหญ่ที่สุดของ FICTECTFUTURE คือเวลาสำหรับการทำงานให้สำเร็จเช่นกัน
Future.complete (60);
ใช้ในการตั้งค่าเวลาเสร็จ
การดำเนินการแบบอะซิงโครนัสของ FICTECTE -FUTURE:
การคำนวณจำนวนเต็มสาธารณะแบบคงที่ (จำนวนเต็มพารา) {ลอง {// จำลองเธรดการดำเนินการยาว ๆ (1,000); } catch (interruptedException e) {} return para * para; } โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException, ExecutionException {Final CompletableFuture <Integer> Future = PrectiveFuture .supplyasync (() -> calc (50)); System.out.println (future.get ()); } สตรีมมิ่งการโทรของ FICTECABLEFUTURE: Public Static Integer Calc (Integer Para) {ลอง {// จำลองเธรดการดำเนินการที่ยาวนาน (1,000); } catch (interruptedException e) {} return para * para; } โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException, ExecutionException {PrectiableFuture <Void> FU = PrectiveFuture .supplyasync (() -> calc (50)) .Thenaccept (system.out :: println); fu.get (); -รวมหลาย filcleable futures:
calc สาธารณะคงที่สาธารณะ (จำนวนเต็ม para) {return para / 2; } โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException, ExecutionException {PrectiableFuture <Void> FU = PrectiveFuture .supplyasync (() -> calc (50)). thencompose (I) -> "/" "). thenaccept (system.out :: println); fu.get (); - ตัวอย่างเหล่านี้มุ่งเน้นไปที่คุณสมบัติใหม่ ๆ ของ Java 8 นี่คือตัวอย่างบางส่วนเพื่อแสดงคุณสมบัติดังนั้นฉันจะไม่เข้าไปในเชิงลึก
PomptextFuture มีส่วนเกี่ยวข้องกับประสิทธิภาพเพียงเล็กน้อย แต่มีความสำคัญมากกว่าในการสนับสนุนการเขียนโปรแกรมที่ใช้งานได้และการปรับปรุงฟังก์ชั่น แน่นอนว่าการตั้งค่าเวลาเสร็จสมบูรณ์เป็นไฮไลต์
3. Stampedlock
ในบทความก่อนหน้าการแยกล็อคได้ถูกกล่าวถึงและการใช้งานที่สำคัญของการแยกล็อคคือ readwriteLock StampedLock เป็นการปรับปรุง ReadWriteLock ความแตกต่างระหว่าง StampedLock และ ReadWriteLock คือ StampedLock เชื่อว่าการอ่านไม่ควรบล็อกการเขียนและ StampedLock เชื่อว่าเมื่อการอ่านและการเขียนเป็นเอกสิทธิ์เฉพาะบุคคลอ่านควรอ่านซ้ำ การออกแบบนี้แก้ปัญหาการเขียนความหิวโหยเมื่ออ่านมากขึ้นและเขียนน้อยลง
ดังนั้น StampedLock คือการปรับปรุงที่มีแนวโน้มที่จะเขียนเธรด
ตัวอย่าง StampedLock:
นำเข้า java.util.concurrent.locks.stampedlock; Public Class Point {Private Double X, Y; Private Final StampedLock SL = New StampedLock (); โมฆะย้าย (double deltax, double deltay) {// วิธีการล็อคแบบยาวโดยเฉพาะ = sl.writeLock (); ลอง {x += deltax; y += deltay; } ในที่สุด {Sl.UnlockWrite (แสตมป์); }} double marilesfromorigin () {// วิธีการอ่านแบบอ่านอย่างเดียวอย่างเดียว = Sl.TryOptimisticRead (); double currentx = x, currenty = y; if (! sl.validate (แสตมป์)) {stamp = sl.readlock (); ลอง {currentx = x; currenty = y; } ในที่สุด {sl.unlockread (แสตมป์); }} return math.sqrt (currentx * currentx + currenty * currenty); -รหัสข้างต้นจำลองเธรดการเขียนและเธรดการอ่าน StampedLock ตรวจสอบว่าเป็นเอกสิทธิ์เฉพาะบุคคลตามแสตมป์หรือไม่ เมื่อเขียนแสตมป์หนึ่งครั้งมันจะเพิ่มมูลค่าที่แน่นอน
TryoptimisticRead ()
มันเป็นสถานการณ์ที่การอ่านและการเขียนไม่ได้เกิดร่วมกันตามที่กล่าวไว้
ทุกครั้งที่คุณอ่านเธรดคุณจะตัดสินก่อน
if (! sl.validate (แสตมป์))
ในการตรวจสอบจะต้องตรวจสอบก่อนว่ามีการเขียนเธรดการเขียนหรือไม่จากนั้นพิจารณาว่าค่าอินพุตนั้นเหมือนกับแสตมป์ปัจจุบันนั่นคือตรวจสอบว่าเธรดอ่านจะอ่านข้อมูลล่าสุดหรือไม่
หากมีการเขียนเธรดการเขียนหรือค่าแสตมป์แตกต่างกันการส่งคืนล้มเหลว
หากการตัดสินล้มเหลวแน่นอนคุณสามารถลองอ่านซ้ำ ๆ ในรหัสตัวอย่างมันไม่ได้รับอนุญาตให้ลองอ่านซ้ำ ๆ แต่แทนที่จะใช้การล็อคในแง่ดีเพื่อลดลงในการอ่านการอ่านทั่วไปเพื่ออ่าน สถานการณ์นี้เป็นวิธีการอ่านในแง่ร้าย
แสตมป์ = sl.readlock ();
แนวคิดการใช้งาน StampedLock:
CLH Spin Lock: เมื่อแอปพลิเคชันล็อคล้มเหลวเธรดอ่านจะไม่ถูกระงับทันที คิวเธรดรอจะถูกเก็บรักษาไว้ในล็อค เธรดทั้งหมดที่ใช้สำหรับล็อค แต่ไม่มีการบันทึกเธรดที่ประสบความสำเร็จในคิวนี้ แต่ละโหนด (หนึ่งโหนดแสดงถึงเธรด) บันทึกบิตล็อคเพื่อตรวจสอบว่าเธรดปัจจุบันได้ปล่อยล็อคหรือไม่ เมื่อเธรดพยายามที่จะได้รับการล็อคมันจะได้รับโหนดหางของคิวการรอคอยปัจจุบันเป็นโหนดรุ่นก่อน และใช้รหัสดังต่อไปนี้เพื่อตรวจสอบว่าโหนด preambled ได้เปิดตัวล็อคสำเร็จ
ในขณะที่ (pred.locked) {
-
ลูปนี้คือการรอให้โหนดก่อนหน้าปล่อยล็อคเพื่อให้เธรดปัจจุบันจะไม่ถูกระงับโดยระบบปฏิบัติการซึ่งจะช่วยปรับปรุงประสิทธิภาพ
แน่นอนว่าจะไม่มีการหมุนที่ไม่มีที่สิ้นสุดและเธรดจะถูกระงับหลังจากสปินหลายครั้ง