2012-01-16 17 views

उत्तर

13

इन दो प्रकारों की पसंद प्रदर्शन पर निर्भर नहीं होना चाहिए। AtomicInteger के लिए मुख्य विकल्प यह है कि यदि आप पूर्णांक पर संचालन के साथ थ्रेड सुरक्षा प्राप्त करना चाहते हैं।

हालांकि परमाणु संचालन के विस्तृत कार्यान्वयन ऑपरेटिंग सिस्टम पर निर्भर करते हुए प्रदर्शन अंतर दृढ़ता से ऑपरेटिंग सिस्टम पर निर्भर हो सकता है।

+3

+1। परमाणु इंटेगर एक गैर-समवर्ती उपयोग-मामले में भी एक सस्ता म्यूटेबल पूर्णांक प्रदान करता है। –

+0

-1: परमाणु इंटेगर मुख्य रूप से प्रदर्शन कारण (लॉक-फ्री डेटा संरचनाओं को लागू करने के लिए) के लिए मौजूद है। यदि थैड सुरक्षा एकमात्र चिंता थी, तो आप सिंक्रनाइज़ेशन का उपयोग कर सकते हैं। –

+2

@ माइकलबोर्गवर्ड: सिर्फ इसलिए कि सिंक्रनाइज़ेशन के साथ थ्रेड-सुरक्षा संभव है इसका मतलब यह नहीं है कि परमाणु इंटेगर थ्रेड-सुरक्षित पूर्णांक संचालन प्रदान नहीं करता है। उत्तर का मुद्दा यह है कि इंटीजर और परमाणु इंटेगर का कच्चा प्रदर्शन एक या दूसरे की पसंद का मार्गदर्शन नहीं करता है। पसंद का उद्देश्य क्या उद्देश्य है: क्या हमें एक परिवर्तनीय थ्रेड-सुरक्षित पूर्णांक की आवश्यकता है, या क्या हम बस एक अपरिवर्तनीय वस्तु में एक पूर्णांक रैप करना चाहते हैं? –

1

बहुत मामूली सिंक्रनाइज़ेशन ओवरहेड के अलावा, नहीं।

5

ठीक है, अगर आप इसे बहुप्रचारित वातावरण में उपयोग करते हैं, उदाहरण के लिए, उदा। काउंटर, तो आप पूर्णांक

public final class Counter { 
    private long value = 0; 
    public synchronized long getValue() { 
    return value; 
    } 

    public synchronized long increment() { 
    return ++value; 
    } 
} 

को synchronize पहुँच करने के लिए है आप तुल्यकालन

public class NonblockingCounter { 
    private AtomicInteger value; 

    public int getValue() { 
     return value.get(); 
    } 

    public int increment() { 
     return value.incrementAndGet(); 
    } 
} 

पढ़ने http://cephas.net/blog/2006/09/06/atomicinteger/

संपादित उपयोग incrementAndGet

सिफारिश के बिना AtomicInteger साथ बेहतर प्रदर्शन किया है सकते हैं
+0

incrementAndGet का उपयोग क्यों नहीं करते? –

+0

आपका मतलब है [getAndIncrement] (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html#getAndIncrement())? खैर, अच्छा सवाल महोदय, मुझे लगता है कि मैं बहुत तेज़ और आलसी था। – bpgergo

+0

नहीं, मेरा मतलब है incrementAndGet। getAndIncrement i ++ लौटने के बराबर होगा। लेकिन आपका पहला स्निपेट वापस ++ i; –

3

AtomicInteger कुछ (सभी नहीं!) संचालन जो अन्यथा विशेष हार्डवेयर निर्देशों का उपयोग कर लॉक-फ्री तरीके से सिंक्रनाइज़ेशन की आवश्यकता होती है। यह प्रदर्शन को कैसे प्रभावित करता है कुछ जटिल है:

  • सबसे पहले, यह एक माइक्रो-ऑप्टिमाइज़ेशन है जो केवल तभी महत्वपूर्ण होगा जब यह विशेष ऑपरेशन आपके एप्लिकेशन के महत्वपूर्ण पथ पर हो।
  • विशेष हार्डवेयर निर्देश गैर-मुख्यधारा के प्लेटफ़ॉर्म पर उपलब्ध नहीं हो सकते हैं, इस स्थिति में AtomicInteger शायद सिंक्रनाइज़ेशन का उपयोग करके कार्यान्वित किया जाएगा।
  • जब कोई विवाद नहीं होता है तो JVM अक्सर लॉकिंग ओवरहेड को ऑप्टिमाइज़ कर सकता है (उदा।, एक थ्रेडेड एप्लिकेशन)। उस स्थिति में, शायद कोई अंतर नहीं है।
  • यदि कम से कम मध्यम लॉक विवाद (यानी एकाधिक धागे हैं, लेकिन वे अधिकतर पूर्णांक तक पहुंचने की तुलना में अन्य चीजें करते हैं), तो लॉक-मुक्त एल्गोरिदम सिंक्रनाइज़ेशन से बेहतर प्रदर्शन करता है।
  • यदि बहुत भारी लॉक विवाद (यानी बहुत सारे थ्रेड जो उस पूर्णांक तक पहुंचने का प्रयास करने में बहुत समय व्यतीत करते हैं), सिंक्रनाइज़ेशन बेहतर प्रदर्शन कर सकता है क्योंकि लॉक-फ्री एल्गोरिदम ऑपरेशन को फिर से प्रयास करने पर आधारित होता है जब यह विफल रहता है एक टक्कर
+1

वास्तव में उन तथ्यों के प्रकार जिन्हें मैं ढूंढ रहा हूं। धन्यवाद। –

0

आज इस पोस्टिंग भर में आया लेकिन मेरे परिणाम (कृपया के रूप में मैं प्रणाली मैं पर इंटरनेट :)

से कनेक्ट नहीं किया गया था यह एक भाग के रूप में निम्नलिखित वर्गों टाइप हाथ था कोड पर कोई टिप्पणी नहीं साझा करना चाहते थे

निष्कर्ष कोड से उत्पादन नीचे के रूप में था इस प्रकार है:

परमाणु परिणाम: बीत चुके = 25,257 एमएस, ExpectedValue = 50000, FinalValue = 50000, सच आदिम परिणाम: बीत चुके = 25,257 एमएस, ExpectedValue = 50000, FinalValue = 48 991, झूठी

मेरे विशेष ऐप में मेरे उपयोग के लिए मैंने मॉनिटरिंग क्लास में स्टेटस नंबरों के लिए परमाणु मूल्यों का उपयोग करना चुना है।यदि कोई और कुछ कठिन परिणाम देखना चाहता था तो मैंने इस जानकारी को पोस्ट करने का विकल्प चुना।

एक अच्छा दिन है!

क्लास:

मैं एक आदिम लंबी और एक परमाणु लंबी और एक्सेसर वेतन वृद्धि के तरीकों, एक IncrementAtomicRunnable और एक IncrementPrimitiveRunnable के साथ एक मुख्य वर्ग बनाया।

LongOverhead:

public class LongOverhead{ 
    AtomicLong atomicLong; 
    long primitiveLong; 

    public LongOverhead(){ 
    atomicLong = new AtomicLong(0l); 
    primitiveLong = 0l; 
    } 

    public void incrAtomicLong(){ 
    atomicLong.getAndAdd(1l); 
    } 

    public long getAtomicLong(){ 
    return atomicLong.get(); 
    } 

    public void incrPrimitiveLong(){ 
    primitiveLong++; 
    } 

    public long getPrimitiveLong(){ 
    return primitiveLong; 
    } 

    public static void main(String [] args){ 
    String template = "%s Results: Elapsed = %d ms, ExpectedValue = %d, FinalValue = %d, %b"; 

    int loopTotal = 1000; 
    int waitMilliseconds = 25; 
    int totalThreads = 50; 
    int expectedValue = loopTotal * totalThreads; 
    int whileSleep = 250; 

    LongOverhead atomic = new LongOverhead(); 
    LongOverhead primitive = new LongOverhead(); 

    List<Thread> atomicThreads = new ArrayList<>(); 
    List<Thread> primitiveThreads = new ArrayList<>(); 

    for(int x=0;x<totalThreads;x++){ 
     Thread a = new Thread(new IncrementalAtomicRunnable(atomic, loopTotal, waitMilliseconds), "AtomicIncr" + x); 
     atomicThreads.add(a); 

     Thread p = new Thread(new IncrementalPrimitiveRunnable(primitive, loopTotal, waitMilliseconds), "PrimitiveIncr" + x); 
     primitiveThreads.add(p); 
    } 

    boolean cont = true; 
    long atomicStart = System.currentTimeMillis(); 
    for(Thread t: atomicThreads){ 
     t.start(); 
    } 

    while(cont){ 
     try{ 
     Thread.sleep(whileSleep); 
     }catch(InterruptedException e){ 
     e.printStackTrace(); 
     } 

     boolean foundAlive = false; 
     for(Thread t: atomicThreads){ 
     foundAlive = (State.TERMINATED != t.getState()); 
     if(foundAlive){ 
      break; 
     } 
     } 

     cont = foundAlive; 

    } 

    long atomicFinish = System.currentTimeMillis(); 
    long atomicElapsed = atomicFinish - atomicStart; 
    long atomicFinal = atomic.getAtomicLong(); 

    cont = true; 
    long primitiveStart = System.currentTimeMillis(); 
    for(Thread t: primitiveThreads){ 
     t.start(); 
    } 

    while(cont){ 
     try{ 
     Thread.sleep(whileSleep); 
     }catch(InterruptedException e){ 
     e.printStackTrace(); 
     } 

     boolean foundAlive = false; 
     for(Thread t: primitiveThreads){ 
     foundAlive = (State.TERMINATED != t.getState()); 
     if(foundAlive){ 
      break; 
     } 
     } 

     cont = foundAlive; 
    long primitiveFinish = System.currentTimeMillis(); 
    long primitiveElapsed = primitiveFinish - primitiveStart; 
    long primitiveFinal = primitive.getPrimitiveLong(); 

    System.out.println(String.format(template, "ATOMIC", atomicElapsed, expectedValue, atomicFinal, (expectedValue==atomicFinal))); 
    System.out.println(String.format(template, "PrImItIvE", primitiveElapsed, expectedValue, primitiveFinal, (expectedValue==primitiveFinal))); 
    } 

IncrementAtomicRunnable:

public class IncrementAtomicRunnable implements Runnable{ 
    protected LongOverhead oh; 
    protected int loopTotal; 
    protected int waitMilliseconds; 
    protected String currentThreadName; 

    public IncrementAtomicRunnable(LongOverhead oh, int loopTotal, int waitMilliseconds){ 
    this.oh = oh; 
    this.loopTotal = loopTotal; 
    this.waitMilliseconds = waitMilliseconds; 
    } 

    @Override 
    public void run(){ 
    currentThreadName = Thread.currentThread().getName(); 
    System.out.println(currentThreadName + " for ATOMIC is starting....."); 
    for(int x=0;x<loopTotal;x++){ 
     oh.incrAtomicLong(); 
     try{ 
     Thread.sleep(waitMilliseconds); 
     }catch(InterruptedException e){ 
     System.out.println("InterruptedThread[" + currentThreadName + "], eating exception @@@@@"); 
     } 
    } 

    System.out.println("....." + currentThreadName + " for ATOMIC is finished."); 
    } 
} 

और अंत में IncrementPrimitiveRunnable:

public class IncrementPrimitiveRunnable extends IncrementAtomicRunnable{ 
    public IncrmentPrimitiveRunnable(LongOverhead oh, int loopTotal, int waitMilliseconds){ 
    super(oh, loopTotal, waitMilliseconds); 
    } 

    @Override 
    public void run(){ 
    super.currentThreadName = Thread.currentThread().getName(); 
    System.out.println(currentThreadName + " for PRIMITIVE is starting....."); 
    for(int x=0;x<loopTotal;x++){ 
     oh.incrPrimitiveLong(); 
     try{ 
     Thread.sleep(waitMilliseconds); 
     }catch(InterruptedException e){ 
     System.out.println("InterruptedThread[" + currentThreadName + "], eating exception @@@@@"); 
     } 
    } 

    System.out.println("....." + currentThreadName + " for PRIMITIVE is finished."); 
    } 
} 
संबंधित मुद्दे