জাভা সিঙ্গেলটন এবং সিঙ্ক্রোনাইজেশন


117

দয়া করে সিঙ্গেলটন এবং মাল্টিথ্রেডিং সম্পর্কিত আমার প্রশ্নগুলি স্পষ্ট করুন:

  • বহুবিবাহিত পরিবেশে জাভাতে সিঙ্গেলটন কার্যকর করার সর্বোত্তম উপায় কী?
  • যখন একাধিক থ্রেড getInstance() একই সাথে পদ্ধতিতে অ্যাক্সেস করার চেষ্টা করে তখন কী ঘটে ?
  • আমরা কি সিঙ্গলটনের তৈরি করতে পারি getInstance() synchronized?
  • সিঙ্গেলটন ক্লাস ব্যবহার করার সময় কি আসলেই সিঙ্ক্রোনাইজেশন প্রয়োজন?

উত্তর:


211

হ্যাঁ, এটি প্রয়োজনীয়। অলস সূচনা সহ থ্রেড সুরক্ষা অর্জন করতে আপনি বিভিন্ন পদ্ধতি ব্যবহার করতে পারেন:

ড্রাকোনিয়ান সিঙ্ক্রোনাইজেশন:

private static YourObject instance;

public static synchronized YourObject getInstance() {
    if (instance == null) {
        instance = new YourObject();
    }
    return instance;
}

এই সমাধানটির জন্য প্রতিটি থ্রেডকে সিঙ্ক্রোনাইজ করা প্রয়োজন যখন বাস্তবে কেবল প্রথম কয়েকটি হওয়া দরকার।

ডাবল চেক সিঙ্ক্রোনাইজেশন :

private static final Object lock = new Object();
private static volatile YourObject instance;

public static YourObject getInstance() {
    YourObject r = instance;
    if (r == null) {
        synchronized (lock) {    // While we were waiting for the lock, another 
            r = instance;        // thread may have instantiated the object.
            if (r == null) {  
                r = new YourObject();
                instance = r;
            }
        }
    }
    return r;
}

এই সমাধানটি নিশ্চিত করে যে কেবলমাত্র প্রথম কয়েকটি থ্রেড যা আপনার সিঙ্গলটন অর্জন করার চেষ্টা করে তা লক অর্জনের প্রক্রিয়াটি পেরিয়ে যেতে হবে।

দাবিতে শুরু :

private static class InstanceHolder {
    private static final YourObject instance = new YourObject();
}

public static YourObject getInstance() {
    return InstanceHolder.instance;
}

এই সমাধানটি থ্রেড সুরক্ষা নিশ্চিত করতে শ্রেণি সূচনা সম্পর্কে জাভা মেমরি মডেলের গ্যারান্টিগুলির সুবিধা গ্রহণ করে। প্রতিটি ক্লাস কেবল একবার লোড করা যায় এবং এটি কেবল যখন প্রয়োজন হয় তখন লোড হবে। এর অর্থ getInstanceহ'ল প্রথমবার বলা হয়, InstanceHolderলোড instanceহবে এবং তৈরি হবে এবং যেহেতু এটি ClassLoaderএস দ্বারা নিয়ন্ত্রিত হয় , তাই কোনও অতিরিক্ত সিঙ্ক্রোনাইজেশন প্রয়োজন হয় না।


23
সতর্কতা - ডাবল-চেক করা সিঙ্ক্রোনাইজেশনে সতর্কতা অবলম্বন করুন। এটি মেমরির মডেলটির সাথে "সমস্যাগুলির" কারণে জাভা-পূর্ব জেভিএম-এর সাথে সঠিকভাবে কাজ করে না।
স্টিফেন সি

3
-1 Draconian synchronizationএবং Double check synchronizationgetInstance () - পদ্ধতি অবশ্যই অচল থাকতে হবে!
গ্রিম

2
@PeterRader তারা না প্রয়োজন হতে static, কিন্তু এটা আরো জানার জন্য হতে পারে যদি তারা ছিল। অনুরোধ অনুসারে সংশোধিত।
জেফ্রি

4
আপনি ডাবল চেকড লক প্রয়োগের কাজের গ্যারান্টিযুক্ত নয়। ডাবল চেকড লকিংয়ের জন্য আপনি যে নিবন্ধটি উদ্ধৃত করেছেন তাতে এটি আসলে ব্যাখ্যা করা হয়েছে। :) সেখানে উদ্বায়ী ব্যবহার করে একটি উদাহরণ রয়েছে যা 1.5 এবং উচ্চতর জন্য সঠিকভাবে কাজ করে (ডাবল চেকড লকিং কেবল 1.5 এর নীচে সরল ভাঙা)। চাহিদা ধারকটির সূচনাটি নিবন্ধেও উদ্ধৃত করা সম্ভবত আপনার উত্তরের একটি সহজ সমাধান হতে পারে।
আটকে আট

2
@ মিডিয়ামওন আফাইক, rনির্ভুলতার জন্য প্রয়োজন নেই। একটি স্থানীয় পরিবর্তনশীল অ্যাক্সেস চেয়ে অনেক ব্যয়বহুল, যেহেতু অস্থির ক্ষেত্র অ্যাক্সেস এড়ানোর জন্য এটি কেবল একটি অপ্টিমাইজেশন।
জেফ্রি

69

এই প্যাটার্নটি সুসংগত সিঙ্ক্রোনাইজেশন ছাড়াই থ্রেড-নিরাপদ অলস-সূচনা দেয় !

public class MySingleton {

     private static class Loader {
         static final MySingleton INSTANCE = new MySingleton();
     }

     private MySingleton () {}

     public static MySingleton getInstance() {
         return Loader.INSTANCE;
     }
}

এটি কাজ করে কারণ এটি ক্লাস লোডারটি আপনার জন্য সমস্ত সিঙ্ক্রোনাইজেশন বিনামূল্যে করার জন্য ব্যবহার করে: ক্লাসটি MySingleton.Loaderপ্রথমে getInstance()পদ্ধতির অভ্যন্তরে প্রবেশ করা হয় , সুতরাং Loaderযখন getInstance()প্রথমবারের জন্য ডাকা হয় তখন শ্রেণি লোড হয়। আরও, শ্রেণি লোডার গ্যারান্টি দেয় যে আপনি ক্লাসে অ্যাক্সেস পাওয়ার আগে সমস্ত স্থির সূচনা সম্পন্ন হয়েছে - এটিই আপনাকে থ্রেড-সুরক্ষা দেয়।

এটা যাদু মত।

এটি আসলে ঝুর্তাদোর এনাম প্যাটার্নের সাথে খুব মিল, তবে আমি এনাম প্যাটার্নটিকে এনাম ধারণার অপব্যবহার বলে মনে করি (যদিও এটি কাজ করে)


11
সিঙ্ক্রোনাইজেশনটি এখনও উপস্থিত রয়েছে, এটি কেবল প্রোগ্রামার দ্বারা জেভিএম দ্বারা প্রয়োগ করা হয়েছে।
জেফ্রি

@ জেফ্রে আপনি অবশ্যই বলছেন - আমি এগুলি সব লিখছিলাম (সম্পাদনাগুলি দেখুন)
বোহেমিয়ান

2
আমি বুঝতে পেরেছি এটি JVM এর সাথে কোনও পার্থক্য করে না, আমি কেবল বলছি স্ব-ডকুমেন্টেড কোড যতদূর যায় আমার পক্ষে এটি একটি তাত্পর্যপূর্ণ। আমি জাভাতে সমস্ত ক্যাপগুলি "চূড়ান্ত" কীওয়ার্ড (বা এনাম) এর আগে কখনও দেখিনি, কিছুটা জ্ঞানীয় বিভেদ পেয়েছি। জাভা পুরো সময়ের জন্য প্রোগ্রামিং করা কারও পক্ষে এটি সম্ভবত কোনও তাত্পর্যপূর্ণ হবে না, তবে আপনি যদি ভাষা পিছনে পিছনে লাফিয়ে থাকেন তবে তা স্পষ্ট হতে সহায়তা করে। দম্পতি নবাবিদের জন্য। যদিও, আমি নিশ্চিত যে কেউ এই স্টাইলে খুব দ্রুত খাপ খাইয়ে নিতে পারবেন; সমস্ত ক্যাপ সম্ভবত যথেষ্ট। নিট বাছাই করা মানে না, আমি আপনার পোস্ট পছন্দ করেছি।
রুবি 16

1
দুর্দান্ত উত্তর, যদিও আমি এর কিছু অংশ পাইনি। আপনি কী আরও বিশদ দিতে পারেন "ক্লাস লোডার গ্যারান্টি দেয় যে আপনি ক্লাসে অ্যাক্সেস পাওয়ার আগে সমস্ত স্ট্যাটিক ইনিশিয়ালাইজেশন সম্পূর্ণ হয়ে গেছে - এটিই আপনাকে থ্রেড-সুরক্ষা দেয়।" , কীভাবে এটি থ্রেড সুরক্ষায় সহায়তা করে, আমি সে সম্পর্কে কিছুটা বিভ্রান্ত।
গৌরব জাইন

2
@ wz366 আসলে, যদিও এটি প্রয়োজনীয় নয়, আমি শৈলীর কারণে সম্মত হই (যেহেতু এটি কার্যকরভাবে চূড়ান্ত কারণ অন্য কোনও কোড এটি অ্যাক্সেস করতে finalপারে না) যুক্ত করা উচিত। সম্পন্ন.
বোহেমিয়ান

21

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

public enum Singleton {
    SINGLE;
    public void myMethod(){  
    }
}

এবং তারপরে আপনার থ্রেডগুলি আপনার উদাহরণটি ব্যবহার করুন:

Singleton.SINGLE.myMethod();

8

হ্যাঁ, আপনাকে getInstance()সিঙ্ক্রোনাইজ করা দরকার । যদি এটি না হয় তবে এমন পরিস্থিতি তৈরি হতে পারে যেখানে শ্রেণীর একাধিক উদাহরণ তৈরি করা যেতে পারে।

আপনার দুটি থ্রেড রয়েছে এমন ক্ষেত্রে বিবেচনা করুন getInstance()যা একই সাথে কল করে। এখন কল্পনা করুন যে টি 1 instance == nullচেকের ঠিক আগে চলেছে , এবং তারপরে টি 2 রান করে। এই মুহুর্তে উদাহরণটি তৈরি করা বা সেট করা হয় না, তাই টি 2 চেকটি পাস করবে এবং উদাহরণটি তৈরি করবে। এখন কল্পনা করুন যে এক্সিকিউশনটি টি 1 তে ফিরে আসে। এখন সিঙ্গলটন তৈরি হয়েছে, তবে টি 1 ইতিমধ্যে চেকটি করেছে! এটি আবার অবজেক্টটি তৈরি করতে এগিয়ে যাবে! মেকিং getInstance()সিঙ্ক্রোনাইজ প্রতিরোধ এই সমস্যা।

সিঙ্গলটনের থ্রেড-নিরাপদ করার কয়েকটি উপায় রয়েছে তবে getInstance()সিঙ্ক্রোনাইজ করা বোধহয় সবচেয়ে সহজ।


এটি সম্পূর্ণ পদ্ধতি সিঙ্ক্রোনাইজেশনের পরিবর্তে সিঙ্ক্রোনাইজড ব্লকে অবজেক্ট তৈরি কোড স্থাপন করে সহায়তা করবে?
রিকড্যাভিস

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

7

এনাম সিঙ্গলটন

থ্রেড-সেফ একটি সিঙ্গেলটন কার্যকর করার সহজ উপায় হ'ল এনুম ব্যবহার করা

public enum SingletonEnum {
  INSTANCE;
  public void doSomething(){
    System.out.println("This is a singleton");
  }
}

এই কোডটি জাভা 1.5 তে এনামের প্রবর্তনের পর থেকে কাজ করে

ডাবল চেক লক করা

আপনি যদি একটি "ক্লাসিক" সিঙ্গলটন কোড করতে চান যা বহুবিবাহিত পরিবেশে কাজ করে (জাভা 1.5 থেকে শুরু করে) আপনার এটি ব্যবহার করা উচিত।

public class Singleton {

  private static volatile Singleton instance = null;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (instance == null) {
      synchronized (Singleton.class){
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance ;
  }
}

এটি 1.5 এর আগে থ্রেড-নিরাপদ নয় কারণ উদ্বায়ী কীওয়ার্ডের প্রয়োগটি ভিন্ন ছিল।

প্রারম্ভিক লোডিং সিঙ্গলটন (জাভা 1.5 এর আগেও কাজ করে)

ক্লাসটি লোড হয়ে গেলে এবং থ্রেড সুরক্ষা সরবরাহ করে যখন এই বাস্তবায়নটি সিঙ্গেলটন তাত্ক্ষণিক করে।

public class Singleton {

  private static final Singleton instance = new Singleton();

  private Singleton() {
  }

  public static Singleton getInstance() {
    return instance;
  }

  public void doSomething(){
    System.out.println("This is a singleton");
  }

}

2

ক্লাস লোডে ইনস্ট্যান্টেট করতে এবং থ্রেড সিঙ্ক্রোনাইজেশন সমস্যাগুলি প্রতিরোধ করতে আপনি স্ট্যাটিক কোড ব্লকও ব্যবহার করতে পারেন।

public class MySingleton {

  private static final MySingleton instance;

  static {
     instance = new MySingleton();
  }

  private MySingleton() {
  }

  public static MySingleton getInstance() {
    return instance;
  }

}

@ ভিমশা আরও কয়েকটি জিনিস 1. আপনার instanceচূড়ান্ত করা উচিত 2. আপনি getInstance()স্থির করা উচিত ।
জন ভিন্ট

আপনি যদি সিঙ্গলটনে একটি থ্রেড তৈরি করতে চান তবে আপনি কী করবেন।
অরুণ জর্জ

@ অরুন-জর্জে একটি থ্রেড পুল, প্রয়োজনে একটি একক থ্রেড পুল ব্যবহার করুন এবং কিছুক্ষণের সাথে (সত্য) যদি আপনি নিশ্চিত করতে চান যে আপনার থ্রেডটি কখনও মারা যায় না, ত্রুটি যাই হোক না কেন?
tgkprog

0

বহুবিবাহিত পরিবেশে জাভাতে সিঙ্গেলটন কার্যকর করার সর্বোত্তম উপায় কী?

সিঙ্গেলটন বাস্তবায়নের সর্বোত্তম উপায়ে এই পোস্টটি দেখুন।

জাভাতে সিঙ্গলটন প্যাটার্ন কার্যকর করার কার্যকর উপায় কী?

যখন একাধিক থ্রেড একই সাথে getInstance () পদ্ধতি অ্যাক্সেস করার চেষ্টা করে তখন কী ঘটে?

এটি আপনি পদ্ধতিটি যেভাবে প্রয়োগ করেছেন তার উপর নির্ভর করে I আপনি যদি অস্থায়ী পরিবর্তনশীল ছাড়াই ডাবল লকিং ব্যবহার করেন তবে আপনি আংশিকভাবে সিঙ্গেলটন অবজেক্ট তৈরি করতে পারেন।

আরও তথ্যের জন্য এই প্রশ্নটি দেখুন:

ডাবল চেকড লকিংয়ের এই উদাহরণে কেন অস্থির ব্যবহার করা হয়

আমরা কি সিঙ্গলটনের getInstance () সিঙ্ক্রোনাইজ করতে পারি?

সিঙ্গেলটন ক্লাস ব্যবহার করার সময় কি আসলেই সিঙ্ক্রোনাইজেশন প্রয়োজন?

আপনি যদি নীচের উপায়ে সিঙ্গেলটন প্রয়োগ করেন তবে প্রয়োজন হয় না

  1. স্থিতিশীল অন্তর্ভুক্তি
  2. enum
  3. ইনিশিয়ালেশন-অন-ডিমান্ড_হোল্ডার_আইডিওম সহ অলস আইনিটাইলেজেশন

আরও বিশদ পূর্বে এই প্রশ্নটি দেখুন

জাভা সিঙ্গলটন ডিজাইনের প্যাটার্ন: প্রশ্ন


0
public class Elvis { 
   public static final Elvis INSTANCE = new Elvis();
   private Elvis () {...}
 }

সূত্র: কার্যকর জাভা -> আইটেম 2

এটি ব্যবহার করার পরামর্শ দেয়, যদি আপনি নিশ্চিত হন যে ক্লাস সর্বদা সিঙ্গলটন থাকবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.