জাভাতে কোনও শ্রেণীর বিভিন্ন উদাহরণ চলমান থ্রেডগুলির মধ্যে একটি স্থিতিশীল পরিবর্তনশীল কীভাবে সমন্বয় করবেন?


120

আমি জানি যে synchronizeকোনও পদ্ধতির আগে কীওয়ার্ড ব্যবহার করা সেই বস্তুর সাথে সিঙ্ক্রোনাইজেশন নিয়ে আসে। অর্থাৎ বস্তুর একই উদাহরণে চলমান 2 টি থ্রেড সিঙ্ক্রোনাইজ হবে।

তবে, যেহেতু সিঙ্ক্রোনাইজেশন অবজেক্ট স্তরে রয়েছে তাই 2 টি থ্রেড অবজেক্টের বিভিন্ন দৃষ্টান্তে সিঙ্ক্রোনাইজ হবে না। আমাদের যদি জাভা ক্লাসে স্ট্যাটিক ভেরিয়েবল থাকে যা পদ্ধতি দ্বারা ডাকা হয়, আমরা এটি ক্লাসের উদাহরণগুলিতে সিঙ্ক্রোনাইজ করতে চাই। দুটি উদাহরণ দুটি পৃথক থ্রেডে চলছে।

আমরা কি নিম্নলিখিত উপায়ে সিঙ্ক্রোনাইজেশন অর্জন করতে পারি?

public class Test  
{  
   private static int count = 0;  
   private static final Object lock= new Object();    
   public synchronized void foo() 
  {  
      synchronized(lock)
     {  
         count++;  
     }  
  }  
}

এটি সত্য যেহেতু আমরা lockস্থিতিশীল কোনও বস্তুর সংজ্ঞা দিয়েছি এবং আমরা synchronizedসেই লকের জন্য কীওয়ার্ডটি ব্যবহার করছি, স্ট্যাটিক ভেরিয়েবলটি countএখন শ্রেণীর উদাহরণগুলিতে সিঙ্ক্রোনাইজ হয়ে গেছে Test?


4
লক অবজেক্টটি ফাইনাল হিসাবে ঘোষণা না করা হলে এই সমস্ত উত্তরগুলি ব্যবহারযোগ্য!

এছাড়াও java.util.concurrent.atomic.AtomicInteger দেখুন
রাউন্ডস্প্যারো হিলিটেক্স

উত্তর:


193

স্ট্যাটিক ভেরিয়েবলের অ্যাক্সেস সিঙ্ক্রোনাইজ করার বিভিন্ন উপায় রয়েছে।

  1. একটি সিঙ্ক্রোনাইজড স্ট্যাটিক পদ্ধতি ব্যবহার করুন। এটি ক্লাস অবজেক্টে সিঙ্ক্রোনাইজ হয়।

    public class Test {
        private static int count = 0;
    
        public static synchronized void incrementCount() {
            count++;
        }
    } 
    
  2. ক্লাস অবজেক্টে স্পষ্টতই সিঙ্ক্রোনাইজ করুন।

    public class Test {
        private static int count = 0;
    
        public void incrementCount() {
            synchronized (Test.class) {
                count++;
            }
        }
    } 
    
  3. কিছু অন্যান্য স্থির বস্তুর সাথে সিঙ্ক্রোনাইজ করুন।

    public class Test {
        private static int count = 0;
        private static final Object countLock = new Object();
    
        public void incrementCount() {
            synchronized (countLock) {
                count++;
            }
        }
    } 
    

3 পদ্ধতি অনেক ক্ষেত্রে সেরা কারণ লক অবজেক্টটি আপনার শ্রেণীর বাইরে প্রকাশিত হয় না।


1
১. প্রথমটির এমনকি লক অবজেক্টের দরকার নেই, এটি কি সেরা হওয়া উচিত নয়?
বায়ান হুয়াং

4
২. অস্থির হিসাবে গণনা ঘোষিত করাও কাজ করবে, কারণ অস্থির এটি নিশ্চিত করে যে পরিবর্তনশীল সিঙ্ক্রোনাইজড।
বায়ান হুয়াং

9
# 3 সবচেয়ে ভাল কারণ হ'ল কোডের যে কোনও এলোমেলো বিট সিঙ্ক্রোনাইজ হতে পারে Test.classএবং সম্ভাব্যভাবে আপনার দিনটি লুণ্ঠন করতে পারে । এছাড়াও, ক্লাস ইনিশিয়েশনটি অনুষ্ঠিত ক্লাসে একটি তালা দিয়ে চলে, তাই যদি আপনি ক্রেজি ক্লাস ইনিশিয়ালাইজার পেয়ে থাকেন তবে নিজেকে মাথা ব্যথা করতে পারেন। এটি কোনও পঠন / পরিবর্তন / লেখার অনুক্রমের volatileজন্য সহায়তা করে না count++। একটি ভিন্ন উত্তরে যেমন উল্লেখ করা হয়েছে, java.util.concurrent.atomic.AtomicIntegerসম্ভবত এখানে সঠিক পছন্দ।
ফ্যাডেন

4
আপনি যদি অন্য থ্রেড দ্বারা নির্ধারিত সঠিক মানটি পড়তে চান তবে কাউন্টে রিড অপারেশনটিকে সিঙ্ক্রোনাইজ করতে ভুলবেন না। এটিকে অস্থিতিশীল ঘোষণা করা (সিনক্রোনাইজড রাইটিং ছাড়াও) এর সাথেও সহায়তা করবে।
n0rm1e

1
@ ফেরিবিগ নং, আপনি লক করছেন Test.classthisসিঙ্ক্রোনাইজড নন-স্ট্যাটিক পদ্ধতিগুলির জন্য লক হয়ে থাকবে
user3237736

64

যদি আপনি কেবল কোনও কাউন্টার ভাগ করে নিচ্ছেন তবে java.util.concurrent.atomic প্যাকেজ থেকে একটি অ্যাটমিকআইন্টিজার বা অন্য কোনও উপযুক্ত শ্রেণীর ব্যবহার বিবেচনা করুন :

public class Test {

    private final static AtomicInteger count = new AtomicInteger(0); 

    public void foo() {  
        count.incrementAndGet();
    }  
}

3
এটি জাভা 1.5 তে পাওয়া যায়, 1.6 এ নয়।
পাভেল

4

হ্যাঁ এটা সত্য.

আপনি যদি আপনার ক্লাসের দুটি উদাহরণ তৈরি করেন

Test t1 = new Test();
Test t2 = new Test();

তারপরে t1.foo এবং t2.foo উভয়ই একই স্থিতিক বস্তুতে সিঙ্ক্রোনাইজ করে এবং সুতরাং একে অপরকে অবরুদ্ধ করে।


যত্ন নেওয়া হলে একে অপরকে একবারে বন্ধ করে দেওয়া হবে না।
জাফর আলী

0

আপনি ক্লাসের উপর আপনার কোডটি সিঙ্ক্রোনাইজ করতে পারেন। এটি সহজ হবে।

   public class Test  
    {  
       private static int count = 0;  
       private static final Object lock= new Object();    
       public synchronized void foo() 
      {  
          synchronized(Test.class)
         {  
             count++;  
         }  
      }  
    }

আশা করি আপনি এই উত্তরটি দরকারী বলে মনে করেন।


2
এটি কাজ করবে, তবে @ ফ্যাডডেনের অন্য কোথাও উল্লিখিত হিসাবে, সাবধান থাকুন যে কোনও অন্য থ্রেডও সিনক্রোনাইজ করতে Test.classএবং আচরণকে প্রভাবিত করতে পারে। এজন্যে সিঙ্ক্রোনাইজ lockকরা পছন্দ করা যেতে পারে।
sbk

আপনি যা বলছেন তা সঠিক। সে কারণেই আমি স্পষ্টভাবে উল্লেখ করেছি যে উপরেরটি সহজতম পদ্ধতির।
জাফর আলী

0

স্ট্যাটিক ভেরিয়েবলের সিঙ্ক্রোনাইজেশন অর্জনের জন্য আমরা রিেন্টেন্টলকও ব্যবহার করতে পারি ।

public class Test {

    private static int count = 0;
    private static final ReentrantLock reentrantLock = new ReentrantLock(); 
    public void foo() {  
        reentrantLock.lock();
        count = count + 1;
        reentrantLock.unlock();
    }  
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.