صممت Java بعض الفئات لعدادات الأمان الرقمية ضمن مؤشرات الترابط المتعددة، وتسمى هذه الفئات بالفئات الذرية، وبعضها كما يلي:
java.util.concurrent.atomic.AtomicBoolean;java.util.concurrent.atomic.AtomicInteger;java.util.concurrent.atomic.AtomicLong;java.util.concurrent.atomic.AtomicReference;
فيما يلي اختبار تزايدي لمقارنة قيم AtomicInteger وقيم int العادية ضمن مؤشرات الترابط المتعددة، باستخدام junit4؛
الكود الكامل:
package test.java;import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;import org.junit.Assert;import org.junit.Before;import org.junit.Test;/** * اختبر عملية زيادة AtomicInteger وقيمة int العادية ضمن مؤشرات ترابط متعددة*/public class TestAtomic { // كائن زيادة عدد صحيح ذري public static AtomicInteger counter_integer; // = new AtomicInteger(0); // متغير من النوع int public static int count_int = 0; @Before public void setUp() { // تنفيذ عمل الإعداد الأولي قبل بدء جميع الاختبارات counter_integer = new AtomicInteger(0 } @Test public void testAtomic() throws InterruptedException { // عدد المواضيع التي تم إنشاؤها int threadCount = 100; كم مرة يتم تكرار الخيوط التابعة الأخرى داخليًا int loopCount = 10000600; // التحكم في الكائن المساعد للخيط التابع؛ كائن الموضوع الرئيسي (ينتظر الخيط الرئيسي انتهاء تشغيل جميع الخيوط الفرعية قبل المتابعة) CountDownLatch latch_n = new CountDownLatch(threadCount); 0; i < threadCount; i++) { Thread thread = new AtomicIntegerThread(latch_1, latch_n, loopCount(); } long startNano = System.nanoTime(); // انتظر حتى تنتهي المواضيع الأخرى latch_n.await(); // long endNano = System.nanoTime(); counter_integer.get(); // Assert.assertEquals("المجموع لا يساوي threadCount * loopCount، فشل الاختبار"، sum, threadCount * loopCount System.out.println("--------testAtomic(); ); ); System.out.println("threadCount = " + (threadCount) + ";"); System.out.println("loopCount = " + (loopCount) + ";"); + (sum) + ";"); } @Test public void testIntAdd() throws InterruptedException { // عدد المواضيع التي تم إنشاؤها int threadCount = 100; كم مرة يتم تكرار الخيوط التابعة الأخرى داخليًا int loopCount = 10000600; // التحكم في الكائن المساعد للخيط التابع؛ كائن الموضوع الرئيسي (ينتظر الخيط الرئيسي انتهاء تشغيل جميع الخيوط الفرعية قبل المتابعة) CountDownLatch latch_n = new CountDownLatch(threadCount); 0; i < threadCount; i++) { Thread thread = new IntegerThread(latch_1, latch_n, loopCount()); } long startNano = System.nanoTime(); ); // انتظر حتى تنتهي المواضيع الأخرى latch_n.await(); // long endNano = System.nanoTime(); Assert.assertNotEquals( "المجموع يساوي threadCount * loopCount، فشل اختبار testIntAdd()"، sum, threadCount * loopCount); System.out.println("-------testIntAdd(); من المتوقع أن يكون الاثنان غير متساويين- - -------"); System.out.println("استهلاك الوقت: " + ((endNano - startNano) / (1000*1000))+ "ms"); System.out.println("threadCount = " + (threadCount) + ";"); System.out.println("loopCount = " + (loopCount) + ";"); + (sum) + ";"); // Thread class AtomicIntegerThread Extends Thread { public CountDownLatch = null; AtomicIntegerThread(CountDownLatch latch, CountDownLatch latchdown, int LoopCount) { this.latch = latch; this.latchdown = latchdown; this.loopCount = loopCount; } @Override public void run() { // انتظر مزامنة الإشارة حاول { this.latch انتظر () } Catch (InterruptedException e) { e.printStackTrace() } // for (int i = 0; i < LoopCount; i++) { counter_integer.getAndIncrement(); } // تم تقليل الإشعار بمقدار 1 latchdown.countDown(); } } // فئة الموضوع IntegerThread Extends Thread { public CountDownLatch = null; public IntegerThread(CountDownLatch latch, CountDownLatch latchdown, int LoopCount) { this.latch = latch; this.latchdown = latchdown; this.loopCount = loopCount; } @Override public void run() { // انتظر مزامنة الإشارة حاول { this.latch.await(); }catch (InterruptedException e) { e.printStackTrace(); } // for (int i = 0; i < loopCount; i++) { count_int++ } // يتم تقليل الإشعار بمقدار 1 latchdown.countDown() } }}
نتائج التنفيذ على جهاز كمبيوتر عادي مشابهة لما يلي:
---------------testAtomic(); من المتوقع أن يكون اثنان متساويين ------------------ استهلاك الوقت: 85366msthreadCount = 100;loopCount = 10000600;sum = 1000060000;-----------------testIntAdd(); من غير المتوقع أن يكون الاثنان متساويين -------------- ---- استهلاك الوقت: 1406msthreadCount = 100;loopCount = 10000600;sum = 119428988;
يمكن أن نرى من هذا أن فرق الكفاءة بين عملية AtomicInteger وعملية int يبلغ حوالي 50-80 مرة. بالطبع، تستغرق هذه المقارنة وقتًا طويلاً.
إذا تم تحديده على أنه تنفيذ ذو مؤشر ترابط واحد، فيجب استخدام int وتكون كفاءة تنفيذ العملية int في ظل مؤشرات الترابط المتعددة عالية جدًا، ولا يستغرق الأمر سوى 1.5 ثانية لمليار مرة؛
(بافتراض أن وحدة المعالجة المركزية هي 2 جيجا هرتز، ثنائية النواة و 4 خيوط، والحد الأقصى النظري هو 8 جيجا هرتز، هناك نظريًا 8 مليار دورة ساعة في الثانية.
تستغرق مليار زيادة في Java int 1.5 ثانية، أي 12 مليار عملية محسوبة، وتستهلك كل دورة 12 دورة لوحدة المعالجة المركزية؛
أنا شخصياً أعتقد أن الكفاءة جيدة في لغة C ويجب أن تتطلب أيضًا أكثر من 4 دورات على مدار الساعة (الحكم، تنفيذ التعليمات البرمجية الداخلية، حكم الزيادة التلقائية، القفز)
الفرضية هي: لم يتم تحسين JVM ووحدة المعالجة المركزية بشكل جذري.
)
في الواقع، كفاءة AtomicInteger ليست منخفضة، مليار مرة تستهلك 80 ثانية، ومليون مرة حوالي جزء من الألف، 80 مللي ثانية.