2013-05-03 16 views
7

मैं जावा में थ्रेड सुरक्षा तंत्र को समझने की कोशिश कर रहा हूं और मुझे कुछ मदद चाहिए।जावा में थ्रेड सुरक्षित वैश्विक चर

public class ThreadSafe { 

    private Executor executor = new ScheduledThreadPoolExecutor(5); 

    private long value = 0; 

    public void method() { 
     synchronized (this) { 
      System.out.println(Thread.currentThread()); 
      this.value++; 
     } 
    } 

    private synchronized long getValue() { 
     return this.value; 
    } 

    public static void main(String... args) { 
     ThreadSafe threadSafe = new ThreadSafe(); 
     for (int i = 0; i < 10; i++) { 
      threadSafe.executor.execute(new MyThread()); 
     } 

    } 

    private static class MyThread extends Thread { 

     private ThreadSafe threadSafe = new ThreadSafe(); 

     private AtomicBoolean shutdownInitialized = new AtomicBoolean(false); 

     @Override 
     public void run() { 
      while (!shutdownInitialized.get()) { 
       threadSafe.method(); 
       System.out.println(threadSafe.getValue()); 
      } 
     } 
    } 

} 

यहाँ मैं value धागा सुरक्षित बनाने के लिए कोशिश कर रहा हूँ, एक समय में एक धागा द्वारा केवल पहुँचा जा करने के लिए: मैं एक वर्ग है। जब मैं इस प्रोग्राम को चला रहा हूं, तो मुझे लगता है कि value पर एक से अधिक धागे चल रहे हैं, भले ही मैं इसे synchronized ब्लॉक में लपेटूं। बेशक यह पाश अनंत हो जाएगा लेकिन इसकी सिर्फ एक उदाहरण है, मैं कुछ सेकंड के बाद मैन्युअल रूप से इस कार्यक्रम को रोकने के कर रहा हूँ, इसलिए मैं है:

2470 
Thread[pool-1-thread-3,5,main] 
2470 
Thread[pool-1-thread-5,5,main] 
2470 
Thread[pool-1-thread-2,5,main] 

अलग धागे तक पहुँचने और इस value बदल रहे हैं। क्या कोई मुझे समझा सकता है ऐसा क्यों है? और इस वैश्विक परिवर्तनीय धागे को सुरक्षित कैसे बनाया जाए?

+0

इस उदाहरण में लंबे समय तक स्थिर बनाने के लिए अपने इरादे नहीं था? क्योंकि किसी भी अन्य मामले में कोई थ्रेडसफ्टी मुद्दा नहीं है। –

+0

सुनिश्चित करें कि आप मेरा उत्तर देखें। आपकी 'माई थ्रेड' श्रेणी को 'थॉट' और _should_ 'रननेबल' को लागू नहीं करना चाहिए। – Gray

उत्तर

10

प्रत्येक धागे का अपना ThreadSafe है, और प्रत्येक ThreadSafe का अपना, अलग value है। इसके अलावा, synchronized विधियों को this पर लॉक करें, इसलिए प्रत्येक ThreadSafe स्वयं लॉक हो रहा है - और उनमें से कोई भी धागे के बीच साझा नहीं किया जा रहा है। इसे थ्रेड-लोकलाइटी कहा जाता है, और यह थ्रेड सुरक्षा सुनिश्चित करने का सबसे आसान तरीका है। :)

मुझे लगता है कि प्रयोग करने के लिए आपको MyThread बदलने की आवश्यकता होगी जैसे कि इसके निर्माता ThreadSafe तर्क (एक बनाने के बजाय) लेते हैं। फिर, मुख्य विधि एक ThreadSafe बनाएं और इसे निर्माण समय पर प्रत्येक MyThread पर दें।

4

आपको हर बार एक ही मूल्य मिल रहा है क्योंकि आपके प्रत्येक Runnable के पास ThreadSafe कक्षा का अपना उदाहरण है।

यदि आप उन्हें सभी को एक ही कक्षा साझा करना चाहते हैं, तो आपको केवल ThreadSafe का एक उदाहरण होना होगा और इसे अपनी सभी नौकरियों में पास करना होगा - नीचे देखें। जैसा कि बताया गया है, AtomicLong जाने का तरीका है यदि आप थ्रेड-सुरक्षित साझा long चाहते हैं।

इसके अलावा, आपके MyThread वर्ग extend Thread नहीं होना चाहिए। इसके बजाय implements Runnable होना चाहिए। आपका कोड काम कर रहा है क्योंकि Thread पहले से ही implements Runnable है। यदि आपने myThread.interrupt() किया है तो यह वास्तव में थ्रेड को बाधित नहीं करेगा क्योंकि यह थ्रेड-पूल थ्रेड है जो आपके run() विधि को कॉल कर रहा है।

निम्नलिखित की तरह कुछ काम करेगा:

ThreadSafe threadSafe = new ThreadSafe(); 
for (int i = 0; i < 10; i++) { 
    threadSafe.executor.execute(new MyRunnable(threadSafe)); 
} 
... 
private static class MyRunnable implements Runnable { 
    private final ThreadSafe threadSafe; 
    public MyRunnable(ThreadSafe threadSafe) { 
     this.threadSafe = threadSafe; 
    } 
    ... 
संबंधित मुद्दे