জাভাতে সিঙ্ক্রোনাইজড (এটি) এড়ান?


381

জাভা সিঙ্ক্রোনাইজেশন সম্পর্কে যখনই কোনও প্রশ্ন এসও-তে উঠে আসে তখন কিছু লোক synchronized(this)এড়াতে হবে তা উল্লেখ করতে খুব আগ্রহী । পরিবর্তে, তারা দাবি করে, একটি ব্যক্তিগত রেফারেন্সে একটি লক পছন্দ করা উচিত।

প্রদত্ত কয়েকটি কারণ হ'ল:

আমাকে সহ অন্যান্য লোকেরা যুক্তি দেয় যে synchronized(this)একটি প্রচলিতাসক্তি যা প্রচুর ব্যবহৃত হয় (জাভা লাইব্রেরিতেও) নিরাপদ এবং ভাল বোঝা যায়। এটি এড়ানো উচিত নয় কারণ আপনার একটি বাগ রয়েছে এবং আপনার মাল্টিথ্রেড প্রোগ্রামে কী চলছে তার কোনও ক্লু আপনার নেই। অন্য কথায়: যদি এটি প্রযোজ্য হয়, তবে এটি ব্যবহার করুন।

আমি কিছু বাস্তব-জগতের উদাহরণগুলি দেখতে আগ্রহী (কোনও ফুবারের জিনিস নেই) যেখানে কোনও লক চালু thisকরা এড়ানো ভাল যখন synchronized(this)কাজটি করানোও ভাল ।

অতএব: আপনি কি সর্বদা ব্যক্তিগত এড়াতে synchronized(this)এবং কোনও ব্যক্তিগত রেফারেন্সের তালা দিয়ে প্রতিস্থাপন করা উচিত ?


আরও কিছু তথ্য (উত্তরগুলি দেওয়া হিসাবে আপডেট করা হয়েছে):

  • আমরা উদাহরণ সিঙ্ক্রোনাইজেশন সম্পর্কে কথা বলছি
  • উভয়ই অন্তর্নিহিত ( synchronizedপদ্ধতি) এবং সুস্পষ্ট রূপ synchronized(this)বিবেচনা করা হয়
  • যদি আপনি এই বিষয়টিতে ব্লচ বা অন্যান্য কর্তৃপক্ষকে উদ্ধৃতি দিয়ে থাকেন তবে আপনার পছন্দ মতো অংশগুলি ছেড়ে যাবেন না (উদাহরণস্বরূপ কার্যকর জাভা, থ্রেড সুরক্ষা বিষয়ক আইটেম: সাধারণত এটি উদাহরণস্বরূপ লক, তবে ব্যতিক্রমগুলি রয়েছে))
  • যদি সরবরাহের পরিবর্তে আপনার লকিংয়ে আপনার গ্রানুলারিটির প্রয়োজন হয় synchronized(this)তবে synchronized(this)তা প্রযোজ্য নয় তাই এটি সমস্যা নয়

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

অভ্যন্তরীণ সিঙ্কের অভাবে এবং যখন বাহ্যিক সিঙ্কের প্রয়োজন হয় তখন লকটি প্রায়শই নিজেই হয়ে থাকে, ব্লচ মূলত বলে। তাহলে কেন 'এটি' লক অন দিয়ে অভ্যন্তরীণ সিঙ্কের ক্ষেত্রে এটি হবে না? (ডকুমেন্টেশনের গুরুত্ব আরেকটি বিষয়))
এলজেন্সো

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

1
আমি মনে করি, ডিফেন্সিভ প্রোগ্রামিংয়ের জগতে আপনি বাগগুলি আইডিয়ম দ্বারা নয় কোডের মাধ্যমে প্রতিরোধ করেন। যখন কেউ আমাকে একটি প্রশ্ন জিজ্ঞাসা করে, "আপনার সিঙ্ক্রোনাইজেশনটি কতটা অনুকূল?", আমি "ভেরি" এর পরিবর্তে "খুব" বলতে চাই, যদি না অন্য কেউ এই প্রতিবাদটি অনুসরণ না করে "।
Sgene9

উত্তর:


132

আমি প্রতিটি পয়েন্ট পৃথকভাবে কভার করব।

  1. কিছু অশুভ কোড আপনার লক চুরি করতে পারে (এটি খুব জনপ্রিয়, এটি একটি "দুর্ঘটনাক্রমে" বৈকল্পিকও রয়েছে)

    আমি দুর্ঘটনাক্রমে আরও চিন্তিত । এটির পরিমাণটি হ'ল এটি হ'ল এটি thisআপনার শ্রেণীর উন্মুক্ত ইন্টারফেসের অংশ এবং এটি নথিভুক্ত করা উচিত। কখনও কখনও আপনার লক ব্যবহার করার জন্য অন্যান্য কোডের দক্ষতা পছন্দসই হয়। এটি Collections.synchronizedMap(জাভাদোক দেখুন) মতো বিষয়গুলির ক্ষেত্রে সত্য ।

  2. একই শ্রেণীর মধ্যে সমস্ত সিঙ্ক্রোনাইজড পদ্ধতিতে একই একই লক ব্যবহার করা হয়, যা থ্রুপুট হ্রাস করে

    এটি অত্যধিক সরল চিন্তাভাবনা; শুধু মুক্তি থেকে synchronized(this)সমস্যার সমাধান হবে না won't থ্রুপুটের জন্য সঠিক সিঙ্ক্রোনাইজেশন আরও চিন্তাভাবনা করবে।

  3. আপনি (অযথা) খুব বেশি তথ্য প্রকাশ করছেন

    এটি # 1 এর বৈকল্পিক। ব্যবহার করা synchronized(this)আপনার ইন্টারফেসের অংশ। আপনি যদি এটি / প্রকাশের প্রয়োজন না চান তবে এটি করবেন না।


1. "সিঙ্ক্রোনাইজড" আপনার শ্রেণীর এক্সপোজ ইন্টারফেসের অংশ নয়। 2. সম্মতি 3. দেখুন 1.
এলজেঞ্জো

66
মূলত সিঙ্ক্রোনাইজ (এই) হয় উদ্ভাসিত হয়েছে কারণ এটি এর মানে হল যে বাইরের কোড আপনার ক্লাসের অপারেশন প্রভাবিত করতে পারে। সুতরাং আমি দৃsert়ভাবে বলছি যে আপনার অবশ্যই এটি অবশ্যই ইন্টারফেস হিসাবে নথিভুক্ত করবেন, এমনকি ভাষাটি না হলেও।
ড্যারন

15
অনুরূপ. সংগ্রহের জন্য জাভাডোক দেখুন। সিঙ্ক্রোনাইজড ম্যাপ () - প্রত্যাবর্তিত বস্তু অভ্যন্তরীণভাবে সিঙ্ক্রোনাইজড (এটি) ব্যবহার করে এবং তারা প্রত্যাবর্তনের মতো বৃহত আকারের পারমাণবিক ক্রিয়াকলাপের জন্য একই লকটি ব্যবহার করার জন্য গ্রাহকরা সেটির সুবিধা নেওয়ার প্রত্যাশা করে।
ড্যারন

3
আসলে কালেকশনস.সাইনক্রোনাইজড ম্যাপ () অভ্যন্তরীণভাবে সিঙ্ক্রোনাইজড (এটি) ব্যবহার করে না, এটি একটি ব্যক্তিগত চূড়ান্ত লক অবজেক্ট ব্যবহার করে uses
বাস লাইজডেকার্স

1
@ বাস লাইজডেকারস: ডকুমেন্টেশনটি স্পষ্টভাবে উল্লেখ করেছে যে প্রত্যাবর্তিত মানচিত্রের দৃষ্টান্তে সিঙ্ক্রোনাইজেশন ঘটে। মজার বিষয় হ'ল, মতামতগুলি ফিরে এসেছে keySet()এবং values()(তাদের) লক করে না this, তবে মানচিত্রের উদাহরণটি, যা সমস্ত মানচিত্রের ক্রিয়াকলাপের জন্য নিয়মিত আচরণ পাওয়ার জন্য গুরুত্বপূর্ণ। লক অবজেক্টটি ভেরিয়েবলের মধ্যে রূপান্তরিত করার কারণটি হ'ল SynchronizedSortedMapমূল মানচিত্রের দৃষ্টিতে লক করা উপ-মানচিত্র বাস্তবায়নের জন্য সাবক্লাসের এটির প্রয়োজন।
হোলার

86

ভাল, প্রথমত এটি নির্দেশ করা উচিত যে:

public void blah() {
  synchronized (this) {
    // do stuff
  }
}

শব্দার্থগতভাবে এর সমতুল্য:

public synchronized void blah() {
  // do stuff
}

যা ব্যবহার না করার এক কারণ synchronized(this)। আপনি যুক্তি দিতে পারেন যে আপনি synchronized(this)ব্লকের চারপাশে স্টাফ করতে পারেন । সাধারণ কারণ হ'ল সিঙ্ক্রোনাইজড চেকটি আদৌ চেষ্টা না করা এবং এড়িয়ে যাওয়া, যা সমস্ত ধরণের সম্মতিজনিত সমস্যা বাড়ে, বিশেষত ডাবল চেকড-লকিং সমস্যা , যা তুলনামূলকভাবে সহজ চেক করা কতটা কঠিন হতে পারে তা দেখায় শংকা মুক্ত.

একটি ব্যক্তিগত লক একটি প্রতিরক্ষামূলক ব্যবস্থা, যা কখনই খারাপ ধারণা হয় না।

এছাড়াও, আপনি যেমন ইঙ্গিত করেছেন, ব্যক্তিগত লকগুলি গ্রানুলারিটি নিয়ন্ত্রণ করতে পারে। কোনও সামগ্রীর ক্রিয়াকলাপগুলির একটি সেট অন্যটির সাথে পুরোপুরি সম্পর্কিত নয় তবে synchronized(this)পরস্পর তাদের সকলের অ্যাক্সেস বাদ দেবে।

synchronized(this) সত্যিই তোমাকে কিছু দেয় না


4
"সিঙ্ক্রোনাইজড (এটি) সত্যিই আপনাকে কিছু দেয় না" " ঠিক আছে, আমি এটি একটি সিঙ্ক্রোনাইজ (myPrivateFinalLock) দিয়ে প্রতিস্থাপন করেছি। এটা আমাকে কি দেয়? আপনি এটি একটি প্রতিরক্ষামূলক প্রক্রিয়া সম্পর্কে কথা বলতে। আমি কিসের বিরুদ্ধে সুরক্ষিত?
এলজেঞ্জো

14
আপনি বাহ্যিক বস্তু দ্বারা 'এটি' লক করা দুর্ঘটনাজনিত (বা দূষিত) বিরুদ্ধে সুরক্ষিত।
ক্লিটাস

14
আমি এই উত্তরের সাথে মোটেও একমত নই: সম্ভাব্য সময়ের স্বল্পতম সময়ের জন্য একটি লকটি সর্বদা রাখা উচিত এবং এ কারণেই আপনি পুরো পদ্ধতিটি সিঙ্ক্রোনাইজ করার পরিবর্তে একটি সিঙ্ক্রোনাইজড ব্লকের চারপাশে "স্টাফ" করতে চান তা ঠিক এই কারণ reason ।
অলিভিয়ার

5
সিঙ্ক্রোনাইজড ব্লকের বাইরে স্টাফ করা সর্বদা সুচিন্তিত। মুল বক্তব্যটি হ'ল লোকেরা এই সময়ে অনেক সময় ভুল হয় এবং এটি উপলব্ধি করে না, ঠিক যেমন ডাবল-চেক করা লকিং সমস্যা। নরকের দিকে যাওয়ার রাস্তাটি ভাল উদ্দেশ্য নিয়ে প্রস্তুত করা হয়েছে।
ক্লিটাস

16
আমি সাধারণভাবে "এক্স একটি প্রতিরক্ষামূলক ব্যবস্থা, যা কখনই খারাপ ধারণা হয় না" এর সাথে আমি একমত নই। এই মনোভাবের কারণেই অকারণে অজস্রভাবে ব্লাটড কোড রয়েছে।
ফিনিউ করুন

54

আপনি যখন সিঙ্ক্রোনাইজড (এটি) ব্যবহার করছেন আপনি ক্লাস উদাহরণটি নিজেই লক হিসাবে ব্যবহার করছেন। এর অর্থ হ'ল লকটি থ্রেড 1 দ্বারা অর্জিত হওয়ার পরে, থ্রেড 2 টি অপেক্ষা করা উচিত।

মনে করুন নিম্নলিখিত কোড:

public void method1() {
    // do something ...
    synchronized(this) {
        a ++;      
    }
    // ................
}


public void method2() {
    // do something ...
    synchronized(this) {
        b ++;      
    }
    // ................
}

পদ্ধতি 1 ভেরিয়েবল a এবং পদ্ধতি 2 পরিবর্তনশীল পরিবর্তন করে, দুটি থ্রেড দ্বারা একই ভেরিয়েবলের একযোগে পরিবর্তন এড়ানো উচিত এবং এটি হয়। কিন্তু thread1 পরিবর্তন একটি এবং thread2 পরিবর্তন এটা কোনো জাতি শর্ত ছাড়া সম্পাদনা করা যেতে পারে।

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

সমাধানটি হল দুটি পৃথক ভেরিয়েবলের জন্য 2 টি পৃথক লক ব্যবহার করা :

public class Test {

    private Object lockA = new Object();
    private Object lockB = new Object();

    public void method1() {
        // do something ...
        synchronized(lockA) {
            a ++;      
        }
        // ................
    }


    public void method2() {
        // do something ...
        synchronized(lockB) {
            b ++;      
        }
        // ................
    }

}

উপরের উদাহরণটিতে আরও সূক্ষ্ম দানাদার লক ব্যবহার করা হয়েছে (পরিবর্তে একটিতে দুটি লক ( যথাক্রমে a এবং b ভেরিয়েবলের জন্য লকএ এবং লকবি )) এবং ফলস্বরূপ আরও ভাল সংমিশ্রণের অনুমতি দেয়, অন্যদিকে এটি প্রথম উদাহরণের চেয়ে জটিল হয়ে উঠেছে ...


এটি অত্যন্ত বিপজ্জনক। আপনি এখন একটি ক্লায়েন্ট-সাইড (এই শ্রেণীর ব্যবহারকারীদের) লক অর্ডারিংয়ের প্রয়োজনীয়তা প্রবর্তন করেছেন। যদি দুটি থ্রেড পৃথক ক্রমে মেথড 1 () এবং মেথড 2 () কল করে থাকে তবে তাদের অচলাবস্থার সম্ভাবনা রয়েছে তবে এই শ্রেণীর ব্যবহারকারীর ধারণা নেই যে এটি কেস is
ডেভেব

7
"সিঙ্ক্রোনাইজড (এটি)" দ্বারা সরবরাহিত গ্রানুলারিটি আমার প্রশ্নের ক্ষেত্রের বাইরে। এবং আপনার লক ক্ষেত্রগুলি চূড়ান্ত হওয়া উচিত নয়?
এলজেনসো

10
অচলাবস্থার জন্য আমাদের এ ব্লক থেকে একটি সি সিঙ্ক্রোনাইজ করা ব্লক থেকে বি। দ্যাভের সিঙ্ক্রোনাইজ করা কলটি করা উচিত, আপনি ভুল ...
আন্দ্রেস বাকুরভ

3
আমি যতদূর দেখতে পাচ্ছি এই উদাহরণটিতে কোনও অচলাবস্থা নেই। আমি স্বীকার করি এটা শুধু pseudocode হয় কিন্তু আমি java.util.concurrent.locks.ReentrantLock মত java.util.concurrent.locks.Lock এর বাস্তবায়নের এক ব্যবহার করেন
শন ভাদের

15

যদিও আমি কৌতুকপূর্ণ নিয়মের অন্ধভাবে মেনে চলার বিষয়ে একমত নই, "লক চুরি" পরিস্থিতি কি আপনার কাছে এতটা অভিনব বলে মনে হচ্ছে? একটি থ্রেড প্রকৃতপক্ষে "বাহ্যিকভাবে" ( synchronized(theObject) {...}) আপনার অবজেক্টের লকটি অর্জন করতে পারে , সিঙ্ক্রোনাইজড ইনস্ট্যান্স পদ্ধতিগুলির অপেক্ষায় থাকা অন্য থ্রেডকে ব্লক করে।

আপনি যদি দূষিত কোডে বিশ্বাসী না হন তবে বিবেচনা করুন যে এই কোডটি তৃতীয় পক্ষগুলি থেকে আসতে পারে (উদাহরণস্বরূপ যদি আপনি কোনও প্রকারের অ্যাপ্লিকেশন সার্ভার বিকাশ করেন)।

"দুর্ঘটনাজনক" সংস্করণটি সম্ভবত কম মনে হয় তবে তারা যেমন বলে, "কিছু বোকামি-প্রমাণ তৈরি করুন এবং কেউ আরও ভাল বোকা আবিষ্কার করবেন"।

তাই আমি ক্লাসের কী-তা-নির্ভরতার সাথে নির্ভর করে with


এলজেনসোর প্রথম 3 টি মন্তব্য নিম্নলিখিত সম্পাদনা করুন:

আমি কখনই লক চুরির সমস্যাটি অনুভব করি নি তবে এখানে একটি কাল্পনিক দৃশ্য রয়েছে:

ধরা যাক আপনার সিস্টেমটি একটি সার্লেট পাত্র এবং আমরা যে বিষয়টি বিবেচনা করছি সেটি হ'ল ServletContextবাস্তবায়ন। getAttributeপ্রসঙ্গের বৈশিষ্ট্যগুলি ভাগ করা ডেটা হিসাবে এটির পদ্ধতিটি অবশ্যই থ্রেড-সেফ থাকতে হবে; সুতরাং আপনি এটি হিসাবে ঘোষণা synchronized। আসুন কল্পনাও করুন যে আপনি আপনার ধারক প্রয়োগের ভিত্তিতে একটি সর্বজনীন হোস্টিং পরিষেবা সরবরাহ করেছেন।

আমি আপনার গ্রাহক এবং আপনার সাইটে আমার "ভাল" সার্লেটটি স্থাপন করি। এটি ঘটে যে আমার কোডটিতে একটি কল রয়েছে getAttribute

অন্য একজন গ্রাহক হিসাবে ছদ্মবেশযুক্ত একজন হ্যাকার আপনার দূষিত সার্লেটটি আপনার সাইটে স্থাপন করে। এটি initপদ্ধতিতে নিম্নলিখিত কোড রয়েছে :

সিঙ্ক্রোনাইজড (this.getServletConfig ()। getServletContext ()) {
   (সত্য) {while
}

ধরে নিলাম আমরা একই সার্লেট প্রসঙ্গটি ভাগ করি (দুটি সার্ভলেট একই ভার্চুয়াল হোস্টে থাকা হিসাবে অনুমিত দ্বারা অনুমোদিত), আমার কলটি getAttributeচিরতরে লক হয়ে গেছে। হ্যাকার আমার সার্লেলে একটি ডস অর্জন করেছে।

getAttributeকোনও ব্যক্তিগত লকটিতে সিঙ্ক্রোনাইজ করা থাকলে এই আক্রমণ সম্ভব নয় , কারণ তৃতীয় পক্ষের কোডটি এই লকটি অর্জন করতে পারে না।

আমি স্বীকার করি যে উদাহরণটি স্বীকৃতিপ্রাপ্ত এবং কোনও সার্লেট পাত্রে কীভাবে কাজ করে তার একটি অপ্রকাশ্য দৃষ্টিভঙ্গি, তবে আইএমএইচও এটি বিন্দুটি প্রমাণ করে।

সুতরাং আমি সুরক্ষার বিবেচনার ভিত্তিতে আমার নকশার পছন্দটি করব: উদাহরণগুলির অ্যাক্সেস থাকা কোডটির উপরে কি আমার সম্পূর্ণ নিয়ন্ত্রণ থাকবে? কোনও সূত্রে অনির্দিষ্টকালের জন্য কোনও তালা আটকে রাখার পরিণতি কী হবে?


এটি ক্লাসের উপর নির্ভর করে: এটি যদি কোনও 'গুরুত্বপূর্ণ' অবজেক্ট হয় তবে ব্যক্তিগত রেফারেন্সটি লক করুন? অন্য উদাহরণ লকিং কি যথেষ্ট হবে?
এলজেনসো

6
হ্যাঁ, লক চুরির দৃশ্যটি আমার কাছে অনেক বেশি সুস্পষ্ট মনে হয়েছে। প্রত্যেকেই এর উল্লেখ করেছে, কিন্তু বাস্তবে এটি কে করেছে বা অভিজ্ঞতা হয়েছে? যদি আপনি "দুর্ঘটনাক্রমে" কোনও বস্তু লক করেন যা আপনার করা উচিত নয়, তবে এই ধরণের পরিস্থিতির জন্য একটি নাম রয়েছে: এটি একটি বাগ g ঠিক কর.
এলজেঞ্জো

4
এছাড়াও, অভ্যন্তরীণ রেফারেন্সগুলিতে লক করা "বাহ্যিক সিঙ্ক আক্রমণ" থেকে মুক্ত নয়: আপনি যদি জানেন যে কোডের একটি নির্দিষ্ট সিঙ্কড অংশ কোনও বাহ্যিক ইভেন্ট হওয়ার জন্য অপেক্ষা করে (যেমন ফাইল রাইটিং, ডিবিতে মান, টাইমার ইভেন্ট) আপনি সম্ভবত করতে পারেন এটি পাশাপাশি ব্লক করার ব্যবস্থা করুন।
এলজেঞ্জো

আমাকে স্বীকার করতে দাও যে আমি সেই বোকামিদের মধ্যে একজন, যদিও আমি ছোট ছিলাম did আমি স্পষ্টভাবে লক অবজেক্ট তৈরি না করে কোডটি ক্লিনার বলে মনে করেছি এবং পরিবর্তে, অন্য একটি বেসরকারী চূড়ান্ত অবজেক্টটি ব্যবহার করেছে যা মনিটরে অংশ নিতে হবে needed আমি জানতাম না যে অবজেক্টটি নিজেই একটি সিঙ্ক্রোনাইজ করেছিল। আপনি আসন্ন হাইজিনক্সটি কল্পনা করতে পারেন ...
অ্যালান ক্যাবেরা

12

এটা পরিস্থিতির উপর নির্ভর করে।
যদি কেবল একটি ভাগ করার সত্তা বা একাধিক থাকে more

এখানে পুরো কাজের উদাহরণ দেখুন

একটি ছোট ভূমিকা।

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

সিঙ্ক্রোনাইজড ব্লক
সিঙ্ক্রোনাইজড () ব্লক ভাগ করে নেওয়া যায় এমন সত্তার একযোগে অ্যাক্সেস নিশ্চিত করার একটি উপায়।
প্রথমত, একটি ছোট উপমা
ধরা যাক একটি ওয়াশরুমের ভিতরে দুটি ব্যক্তি পি 1, পি 2 (থ্রেড) একটি ওয়াশবাসিন (শেয়ারযোগ্য সত্তা) রয়েছে এবং সেখানে একটি দরজা (লক) রয়েছে।
এখন আমরা একসাথে একজনকে ওয়াশবাসিন ব্যবহার করতে চাই।
P1 দ্বারা দরজাটি লক করা থাকলে পি
1 তার কাজ শেষ না হওয়া পর্যন্ত P2 অপেক্ষা করে পি 1 দ্বারা দরজাটি লক করা একটি পন্থা পি 1
কেবল দরজাটি আনলক করে তবেই পি 1 ওয়াশবাসিন ব্যবহার করতে পারে।

বাক্য গঠন.

synchronized(this)
{
  SHARED_ENTITY.....
}

"এটি" শ্রেণীর সাথে সম্পর্কিত অন্তর্নিহিত লক সরবরাহ করেছিল (জাভা বিকাশকারী এমনভাবে নকশাকৃত অবজেক্ট শ্রেণিটি তৈরি করেছিল যাতে প্রতিটি বস্তু মনিটরের কাজ করতে পারে)। কেবলমাত্র একটি ভাগ করা সত্তা এবং একাধিক থ্রেড (1: N) থাকলে উপরের পদ্ধতিরটি সূক্ষ্মভাবে কাজ করে। এন শেয়ারেবল সত্তা-এম থ্রেডস এখন এমন পরিস্থিতিটি ভাবুন যখন একটি ওয়াশরুমের ভিতরে দুটি ওয়াশবাসিন থাকে এবং কেবল একটি দরজা থাকে। যদি আমরা পূর্ববর্তী পদ্ধতির ব্যবহার করে থাকি তবে কেবল পি 1 একবারে একটি ওয়াশবাসিন ব্যবহার করতে পারে যখন পি 2 বাইরে অপেক্ষা করবে। এটি সংস্থার অপচয় হওয়ায় কেউ বি 2 (ওয়াশবাসিন) ব্যবহার করছে না। বুদ্ধিমান পন্থা হ'ল ওয়াশরুমের অভ্যন্তরে একটি ছোট ঘর তৈরি করা এবং প্রতি ওয়াশবাসিনে তাদের একটি দরজা সরবরাহ করা। এইভাবে, পি 1 বি 1 অ্যাক্সেস করতে পারে এবং পি 2 বি 2 এবং তদ্বিপরীতটি অ্যাক্সেস করতে পারে।
এখানে চিত্র বর্ণনা লিখুন

washbasin1;  
washbasin2;

Object lock1=new Object();
Object lock2=new Object();

  synchronized(lock1)
  {
    washbasin1;
  }

  synchronized(lock2)
  {
    washbasin2;
  }

এখানে চিত্র বর্ণনা লিখুন
এখানে চিত্র বর্ণনা লিখুন

উপর টপিক দেখুন ----> এখানে


11

এটি নিয়ে সি # এবং জাভা শিবিরে আলাদা aকমত্য রয়েছে বলে মনে হচ্ছে। বেশিরভাগ জাভা কোড ব্যবহার দেখেছি:

// apply mutex to this instance
synchronized(this) {
    // do work here
}

যদিও বেশিরভাগ সি # কোড তর্কযোগ্যভাবে নিরাপদ হয়ে যায়:

// instance level lock object
private readonly object _syncObj = new object();

...

// apply mutex to private instance level field (a System.Object usually)
lock(_syncObj)
{
    // do work here
}

সি # আইডিয়াম অবশ্যই নিরাপদ। পূর্বে উল্লিখিত হিসাবে, লকটিতে কোনও দূষিত / দুর্ঘটনাজনিত অ্যাক্সেস উদাহরণের বাইরে থেকে তৈরি করা যাবে না। জাভা কোডেরও এই ঝুঁকি রয়েছে, তবে মনে হচ্ছে জাভা সম্প্রদায় সময়ের সাথে সাথে কিছুটা কম নিরাপদ, তবে কিছুটা আরও ক্ষুদ্র সংস্করণেও মহাকর্ষ করেছিল।

এটি জাভা বিরুদ্ধে একটি খনন হিসাবে বোঝানো হয় নি, উভয় ভাষায় আমার অভিজ্ঞতা কাজ মাত্র।


3
সম্ভবত যেহেতু সি # একটি অল্প ভাষা, তাই তারা জাভা শিবির এবং কোড স্টাফের মতো আরও ভাল চিত্রগুলি খুঁজে পাওয়া খারাপ প্যাটার্নগুলি থেকে শিখেছে? সেখানে কি কম সিলেটলেট রয়েছে? :)
বিল কে

3
তিনি। বেশ সম্ভবত সত্য, তবে আমি টোপ পর্যন্ত উঠব না! আমার মনে হয় আমি নিশ্চিতভাবে বলতে পারি যে সি # কোডে আরও বড় বড় অক্ষর রয়েছে;)
সার্জ 10

1
ঠিক সত্য নয় (এটি সুন্দরভাবে বলতে)
tcurdt

7

java.util.concurrentপ্যাকেজ অতি আমার থ্রেড নিরাপদ কোডের জটিলতা কমিয়ে দিয়েছে। আমার কাছে কেবলমাত্র কাহিনী প্রমাণ রয়েছে, তবে বেশিরভাগ কাজ আমি যা দেখেছি synchronized(x)তা লক, সেম্যাফোর বা ল্যাচটিকে পুনরায় বাস্তবায়ন করতে দেখা গেছে , তবে নিম্ন-স্তরের মনিটর ব্যবহার করছে।

এটি মাথায় রেখে, এই যেকোন প্রক্রিয়াটি ব্যবহার করে সিঙ্ক্রোনাইজ করা কোনও লক ফাঁস না করে অভ্যন্তরীণ বস্তুতে সিঙ্ক্রোনাইজ করার অনুরূপ। এটি উপকারী যে আপনার দু'বার বা ততোধিক থ্রেড দ্বারা মনিটরে প্রবেশকে নিয়ন্ত্রণ করার বিষয়ে আপনার সম্পূর্ণ নিশ্চিততা রয়েছে।


6
  1. আপনার ডেটা যদি সম্ভব হয় তা finalপরিবর্তনযোগ্য করুন ( পরিবর্তনশীল)
  2. আপনি যদি একাধিক থ্রেড জুড়ে ভাগ করা ডেটার পরিব্যক্তি এড়াতে না পারেন তবে উচ্চ স্তরের প্রোগ্রামিং কনস্ট্রাক্টসগুলি ব্যবহার করুন [যেমন দানাদার Lockএপিআই]

একটি লক একটি ভাগ করা সংস্থার একচেটিয়া অ্যাক্সেস সরবরাহ করে: একবারে কেবল একটি থ্রেড লকটি অর্জন করতে পারে এবং ভাগ করা সংস্থানটিতে সমস্ত অ্যাক্সেসের জন্য লকটি প্রথমে অধিগ্রহণ করা দরকার।

ইন্টারফেস ReentrantLockপ্রয়োগ করে যা ব্যবহারের জন্য নমুনা কোডLock

 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

লক ওভার সিঙ্ক্রোনাইজড সুবিধা (এটি)

  1. সিঙ্ক্রোনাইজড পদ্ধতি বা বিবৃতিগুলির ব্যবহার সমস্ত লক অধিগ্রহণ এবং ব্লক-কাঠামোগত উপায়ে মুক্তি পেতে বাধ্য করে।

  2. লক বাস্তবায়ন সিঙ্ক্রোনাইজড পদ্ধতি এবং বিবৃতি প্রদানের মাধ্যমে অতিরিক্ত কার্যকারিতা সরবরাহ করে

    1. একটি লক অর্জনের একটি অবরুদ্ধ অবরোধ ( tryLock())
    2. লক অর্জনের একটি প্রচেষ্টা যা বাধা দেওয়া যেতে পারে ( lockInterruptibly())
    3. লক অর্জনের একটি প্রচেষ্টা যা সময়সীমা শেষ করতে পারে ( tryLock(long, TimeUnit))।
  3. একটি লক শ্রেণি এমন আচরণ এবং শব্দার্থবিদ্যা সরবরাহ করতে পারে যা অন্তর্ভুক্ত মনিটরের লকের থেকে একেবারে আলাদা

    1. গ্যারান্টিযুক্ত অর্ডার
    2. অ-প্রবেশ প্রবেশ ব্যবহার
    3. ডেডলক সনাক্তকরণ

বিভিন্ন ধরণের সম্পর্কিত এই এসই প্রশ্নটি দেখুন Locks:

সিঙ্ক্রোনাইজেশন বনাম লক

আপনি সিঙ্ক্রোনাইড ব্লকের পরিবর্তে উন্নত সম্মতিযুক্ত API ব্যবহার করে থ্রেড সুরক্ষা অর্জন করতে পারেন। এই ডকুমেন্টেশন পৃষ্ঠাটি থ্রেড সুরক্ষা অর্জনের জন্য ভাল প্রোগ্রামিং কনস্ট্রাক্টস সরবরাহ করে।

লক অবজেক্টস লকিং আইডিয়ামগুলিকে সমর্থন করে যা অনেকগুলি সমবর্তী অ্যাপ্লিকেশনকে সহজতর করে।

এক্সিকিউটাররা থ্রেড চালু এবং পরিচালনা করার জন্য একটি উচ্চ-স্তরের এপিআই সংজ্ঞায়িত করে। Java.util.concurrent দ্বারা প্রদত্ত এক্সিকিউটর বাস্তবায়ন বৃহত-স্কেল অ্যাপ্লিকেশনগুলির জন্য উপযুক্ত থ্রেড পুল পরিচালনা সরবরাহ করে।

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

পারমাণবিক ভেরিয়েবলগুলির এমন বৈশিষ্ট্য রয়েছে যা সিঙ্ক্রোনাইজেশনকে হ্রাস করে এবং মেমরির ধারাবাহিকতা ত্রুটিগুলি এড়াতে সহায়তা করে।

থ্রেডলোক্যালআর্যান্ডম ( জেডিকে in এ) একাধিক থ্রেড থেকে সিউডোরান্ডম সংখ্যার দক্ষ জেনারেশন সরবরাহ করে।

পড়ুন java.util.concurrent এবং java.util.concurrent.atomic অন্যান্য প্রোগ্রামিং নির্মান জন্য খুব প্যাকেজ।


5

যদি আপনি এটি স্থির করেন:

  • আপনার যা করতে হবে তা হ'ল বর্তমান অবজেক্টটি লক করা; এবং
  • আপনি এটিকে পুরো পদ্ধতির চেয়ে ছোট কণিকা দিয়ে লক করতে চান;

তারপরে আমি সিঙ্ক্রোনাইজড (এটি) ওভারের কোনও ট্যাবু দেখছি না।

কিছু লোক ইচ্ছাকৃতভাবে কোনও পদ্ধতির পুরো বিষয়বস্তুর অভ্যন্তরে সিঙ্ক্রোনাইজড (এটি) (পদ্ধতিটিকে সিঙ্ক্রোনাইজড চিহ্নিত করার পরিবর্তে) ব্যবহার করে কারণ তারা মনে করে যে এটি "পাঠকের কাছে পরিষ্কার" কোন বস্তুটি আসলে সংশ্লেষিত হচ্ছে। যতক্ষণ না লোকেরা একটি বুদ্ধিমান পছন্দ করছেন (উদাহরণস্বরূপ বুঝতে পারছেন যে তারা এটি পদ্ধতিতে অতিরিক্ত বাইকোডগুলি প্রকৃতপক্ষে'reোকাচ্ছেন এবং এটি সম্ভাব্য অপটিমাইজেশনের উপর নকআউট প্রভাব ফেলতে পারে), আমি বিশেষত এটির সাথে কোনও সমস্যা দেখছি না don't । আপনার প্রোগ্রামের সমকালীন আচরণটি আপনার সর্বদা নথিভুক্ত করা উচিত, সুতরাং "" সিঙ্ক্রোনাইজড "আচরণটি" এত যুক্তিযুক্ত হিসাবে যুক্তি "প্রকাশ করে দেখছি না।

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


1
"যদি এটি যুক্তি দ্বারা প্রত্যাশিত হতে পারে ..." এমন একটি বিষয় যা আমি চেষ্টা করার চেষ্টাও করছি। আমি সর্বদা ব্যক্তিগত লকগুলি ব্যবহার করার বিন্দুটি দেখতে পাই না , যদিও সাধারণ sensক্যমত্য বলে মনে হয় যে এটি আরও ভাল, যেহেতু এটি আঘাত দেয় না এবং আরও প্রতিরক্ষামূলক হয়।
এলজেঞ্জো

4

আমি মনে করি ব্রায়ান গয়েটসের অনুশীলন জাভা কনকুরન્સી নামে একটি বইতে এই প্রতিটি কেন আপনার বেল্টের অধীনে গুরুত্বপূর্ণ কৌশল তা সম্পর্কে একটি ভাল ব্যাখ্যা রয়েছে is তিনি একটি বিষয় খুব স্পষ্ট করে দিয়েছেন - আপনার অবজেক্টের অবস্থা রক্ষা করতে আপনার অবশ্যই একই লক "সর্বদা" ব্যবহার করতে হবে। সিঙ্ক্রোনাইজড পদ্ধতি এবং কোনও বস্তুর সাথে সিঙ্ক্রোনাইজ করা প্রায়শই হাতে চলে যায়। উদাহরণস্বরূপ ভেক্টর এর সমস্ত পদ্ধতি সিঙ্ক্রোনাইজ করে। যদি আপনার কোনও ভেক্টর অবজেক্টের একটি হ্যান্ডেল থাকে এবং "অনুপস্থিত থাকলে রাখুন" করতে চলেছেন তবে কেবল ভেক্টর তার নিজস্ব নিজস্ব পদ্ধতিগুলি সিঙ্ক্রোনাইজ করা আপনাকে রাষ্ট্রের দুর্নীতি থেকে রক্ষা করতে পারে না। আপনাকে সিঙ্ক্রোনাইজড (ভেক্টরহ্যান্ডল) ব্যবহার করে সিঙ্ক্রোনাইজ করতে হবে। এর ফলে প্রতিটি থ্রেড যা ভেক্টরের কাছে একটি হ্যান্ডেল রাখে এবং একই সাথে ভেক্টরের সামগ্রিক অবস্থা রক্ষা করবে সেম লকটি প্রাপ্ত হবে। একে ক্লায়েন্ট সাইড লকিং বলা হয়। আমরা জানি যে ভেক্টর তার সমস্ত পদ্ধতি সিঙ্ক্রোনাইজ করে (এটি) / সিঙ্ক্রোনাইজ করে এবং তাই অবজেক্ট ভেক্টর হ্যান্ডলে সিঙ্ক্রোনাইজ করার ফলে ভেক্টর অবজেক্টস স্টেটের যথাযথ সিঙ্ক্রোনাইজেশন ঘটতে পারে। আপনি থ্রেড নিরাপদ সংগ্রহ ব্যবহার করছেন বলেই আপনি থ্রেড নিরাপদ তা বিশ্বাস করা বোকামি। কনক্র্যান্টহ্যাশম্যাপ স্পষ্টরূপে putIfAbmitted পদ্ধতি প্রবর্তন করেছিল - এই ধরনের অপারেশনগুলিকে পারমাণবিক করতে।

সংক্ষেপে

  1. পদ্ধতি স্তরে সিঙ্ক্রোনাইজ করা ক্লায়েন্টের পাশের লকিংয়ের অনুমতি দেয়।
  2. আপনার যদি কোনও ব্যক্তিগত লক অবজেক্ট থাকে - এটি ক্লায়েন্টের পাশের লকটিকে অসম্ভব করে তোলে। এটি ঠিক আছে যদি আপনি জানেন যে আপনার ক্লাসে "অনুপস্থিত থাকলে" প্রকারের কার্যকারিতা নেই।
  3. আপনি যদি কোনও লাইব্রেরি ডিজাইন করেন - তবে এটিতে সিঙ্ক্রোনাইজ করা বা পদ্ধতিটি সিঙ্ক্রোনাইজ করা প্রায়শই বুদ্ধিমানের কাজ। কারণ আপনার ক্লাসটি কীভাবে ব্যবহৃত হবে তা আপনি সিদ্ধান্ত নেওয়ার ক্ষেত্রে খুব কমই রয়েছেন।
  4. যদি ভেক্টর কোনও ব্যক্তিগত লক অবজেক্ট ব্যবহার করত - তবে "অনুপস্থিত থাকলে" রাখা ঠিক হবে না। ক্লায়েন্ট কোডটি ব্যক্তিগত লকটিতে কখনই কোনও হ্যান্ডেল অর্জন করতে পারে না এবং এর ফলে তার রাষ্ট্রটি সুরক্ষিত করতে ঠিক একই লকটি ব্যবহারের মৌলিক নিয়মকে ভঙ্গ করে।
  5. এটি বা সিঙ্ক্রোনাইজড পদ্ধতিগুলির সাথে সিঙ্ক্রোনাইজ করার ক্ষেত্রে সমস্যা রয়েছে যেমনটি অন্যরা উল্লেখ করেছে - কেউ একটি লক পেতে পারে এবং এটি কখনই প্রকাশ করতে পারে না। অন্যান্য সমস্ত থ্রেড লকটি প্রকাশের অপেক্ষায় থাকবে।
  6. সুতরাং আপনি কী করছেন তা জেনে নিন এবং সঠিকটি গ্রহণ করুন।
  7. কেউ যুক্তি দিয়েছিলেন যে একটি ব্যক্তিগত লক অবজেক্ট থাকা আপনাকে আরও ভাল গ্রানুলারিটি দেয় - উদাহরণস্বরূপ যদি দুটি ক্রিয়াকলাপ সম্পর্কিত নয় - এগুলি আরও ভাল লুপ দ্বারা সুরক্ষিত হতে পারে যার ফলে আরও ভাল থ্রুপুট পাওয়া যায়। তবে এটি আমার মনে হয় ডিজাইনের গন্ধ এবং কোড গন্ধ নয় - যদি দুটি ক্রিয়াকলাপ সম্পূর্ণরূপে সম্পর্কিত না হয় তবে তারা কেন একই শ্রেণীর অংশ? কোনও ক্লাস ক্লাবের কেন কোনও সম্পর্ক নেই? ইউটিলিটি ক্লাস হতে পারে? হুঁ মিম - কিছু ব্যবহার একই স্ট্রিংয়ের মাধ্যমে স্ট্রিং ম্যানিপুলেশন এবং ক্যালেন্ডারের তারিখের ফর্ম্যাটিং সরবরাহ করে ?? ... কমপক্ষে আমার কোন মানে হয় না !!

3

না, আপনার সবসময় হওয়া উচিত নয় । যাইহোক, যখন আমি কোনও নির্দিষ্ট অবজেক্টের একাধিক উদ্বেগ থাকে যা কেবল নিজের ক্ষেত্রে থ্রেডসেফ হওয়া দরকার তখন আমি এড়াতে চাই। উদাহরণস্বরূপ, আপনার কাছে একটি পরিবর্তনীয় ডেটা অবজেক্ট থাকতে পারে যাতে "লেবেল" এবং "প্যারেন্ট" ক্ষেত্র রয়েছে; এগুলি থ্রেডসেফ হওয়া দরকার, তবে একটি পরিবর্তনের জন্য অন্যকে লিখিত / পড়া থেকে আটকাতে হবে না। (বাস্তবে আমি ক্ষেত্রগুলিকে অস্থির এবং / অথবা java.util.concurrent এর অ্যাটমিকফু র‌্যাপার ব্যবহার করে এড়িয়ে যাব)।

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

আমি বরং আরও দানাদার লক আছে; এমনকি যদি আপনি সমস্ত কিছু পরিবর্তন থেকে থামাতে চান (সম্ভবত আপনি কোনও বিষয়টিকে সিরিয়াল করছেন) তবে একই জিনিস অর্জনের জন্য আপনি কেবল সমস্ত লকই অর্জন করতে পারবেন, এবং এটি আরও সুস্পষ্ট। আপনি যখন ব্যবহার করবেন synchronized(this), আপনি কেন সিঙ্ক্রোনাইজ করছেন ঠিক তার পার্শ্ব প্রতিক্রিয়া কী হতে পারে তা পরিষ্কার নয়। আপনি যদি ব্যবহার করেন synchronized(labelMonitor), বা আরও ভাল labelLock.getWriteLock().lock(), আপনি কী করছেন এবং আপনার সমালোচনামূলক বিভাগের প্রভাবগুলি সীমাবদ্ধ তা স্পষ্ট


3

সংক্ষিপ্ত উত্তর : আপনাকে কোডের উপর নির্ভর করে পার্থক্যটি বুঝতে হবে এবং পছন্দ করতে হবে।

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


আপনি যখন বলছেন এটি আপনার অভিজ্ঞতার উপর নির্ভর করে আমি কি আপনাকে সঠিকভাবে বুঝতে পারি?
এলজেন্সো

প্রথম স্থানে এটি আপনি যে কোডটি লিখতে চান তার উপর নির্ভর করে। কেবল এটিই বলেছিলেন যে আপনি যখন সিংক্রোনাইজ (এটি) ব্যবহার না করার জন্য ডাইভার্ট করেন তখন আপনার আরও কিছুটা অভিজ্ঞতার প্রয়োজন হতে পারে।
tcurdt

2

কোনও লকটি দৃশ্যমানতার জন্য বা সাম্প্রতিক পরিবর্তন থেকে কিছু ডেটা সুরক্ষার জন্য ব্যবহৃত হয় যা দৌড়ের দিকে নিয়ে যেতে পারে।

পারমাণবিক হওয়ার জন্য যখন আপনাকে কেবল আদিম ধরণের ক্রিয়াকলাপ করা দরকার AtomicIntegerতখন পছন্দগুলি এবং পছন্দগুলি উপলভ্য বিকল্প রয়েছে ।

তবে ধরুন আপনার দুটি পূর্ণসংখ্যা রয়েছে যা একে অপরের সাথে সম্পর্কিত xএবং yসমন্বয়গুলির সাথে সম্পর্কিত যা একে অপরের সাথে সম্পর্কিত এবং এটি একটি পারমাণবিক পদ্ধতিতে পরিবর্তন করা উচিত। তারপরে আপনি তাদের একই লক ব্যবহার করে সুরক্ষা দিতেন।

একটি লক কেবল সেই রাষ্ট্রকে রক্ষা করা উচিত যা একে অপরের সাথে সম্পর্কিত। কমও নেই আর নেই। আপনি যদি synchronized(this)প্রতিটি পদ্ধতিতে ব্যবহার করেন তবে শ্রেণির অবস্থা সম্পর্কিত না থাকলেও সমস্ত থ্রেড সম্পর্কিত নয় এমন অবস্থা আপডেট করার পরেও সমস্ত থ্রেড বিতর্কের মুখোমুখি হবে।

class Point{
   private int x;
   private int y;

   public Point(int x, int y){
       this.x = x;
       this.y = y;
   }

   //mutating methods should be guarded by same lock
   public synchronized void changeCoordinates(int x, int y){
       this.x = x;
       this.y = y;
   }
}

উপরের উদাহরণে আমি শুধুমাত্র এক পদ্ধতি আছে যা mutates উভয় xএবং yএবং দুটি ভিন্ন পদ্ধতি যেমন xএবং yসম্পর্কিত হয় এবং যদি আমি mutating জন্য দুটি ভিন্ন পদ্ধতি দিয়েছিলেন xএবং yআলাদাভাবে তারপর এটি হবে হয়েছে না সুতা নিরাপদ।

এই উদাহরণটি কেবল প্রদর্শন করার জন্য এবং এটি কার্যকর করার উপায়টি নয়। এটি করার সর্বোত্তম উপায় হ'ল এটি অনিবার্য করে তোলা

এখন Pointউদাহরণস্বরূপ বিরোধী হিসাবে, TwoCountersইতিমধ্যে @ আন্ড্রেয়াসের সরবরাহের একটি উদাহরণ রয়েছে যেখানে রাষ্ট্র দুটি একে অপরের সাথে সম্পর্কিত না থাকায় দুটি পৃথক লক দ্বারা রক্ষা করা হচ্ছে।

সম্পর্কহীন রাজ্যগুলি রক্ষার জন্য বিভিন্ন লক ব্যবহারের প্রক্রিয়াটিকে লক স্ট্রিপিং বা লক স্প্লিটিং বলা হয়


1

উপর সিঙ্ক্রোনাইজ করতে না কারণ এই যে কখনও কখনও আপনি এক লক বেশী প্রয়োজন (দ্বিতীয় লক প্রায়ই কিছু অতিরিক্ত চিন্তা পর সেটি সরানো, কিন্তু আপনি এখনও অন্তর্বর্তী রাজ্যের এটি প্রয়োজন) হয়। আপনার উপর লক তাহলে এই , আপনি সবসময় মনে রাখা দুই কেশ অন্যতম যা আছে এই ; আপনি যদি কোনও ব্যক্তিগত অবজেক্টটিতে লক করেন তবে ভেরিয়েবলের নামটি আপনাকে তা বলে।

পাঠকের দৃষ্টিকোণ থেকে, আপনি যদি এটিকে লক করতে দেখেন তবে আপনাকে সর্বদা দুটি প্রশ্নের উত্তর দিতে হবে:

  1. কি এক্সেস ধরনের দ্বারা সুরক্ষিত এই ?
  2. একটি লক আসলেই যথেষ্ট, কেউ কি বাগ প্রবর্তন করেনি?

একটি উদাহরণ:

class BadObject {
    private Something mStuff;
    synchronized setStuff(Something stuff) {
        mStuff = stuff;
    }
    synchronized getStuff(Something stuff) {
        return mStuff;
    }
    private MyListener myListener = new MyListener() {
        public void onMyEvent(...) {
            setStuff(...);
        }
    }
    synchronized void longOperation(MyListener l) {
        ...
        l.onMyEvent(...);
        ...
    }
}

যদি দুটি থ্রেড longOperation()দুটি ভিন্ন উদাহরণে শুরু হয় BadObject, তবে তারা তাদের লকগুলি অর্জন করে; যখন অনুরোধ করার সময়টি হয় তখন l.onMyEvent(...)আমাদের একটি অচলাবস্থা থাকে কারণ কোনও থ্রেডই অন্য বস্তুর লক অর্জন করতে পারে না।

এই উদাহরণে আমরা দুটি লক ব্যবহার করে অচলাবস্থা দূর করতে পারি, একটি সংক্ষিপ্ত ক্রিয়াকলাপের জন্য এবং একটি দীর্ঘ লোকের জন্য।


2
এই উদাহরণটিতে অচলাবস্থা পাওয়ার একমাত্র উপায় হ'ল যখন BadObjectকোনও longOperationবি-তে আহ্বান জানায় , এ এর ​​পাশ দিয়ে চলে যায় myListenerএবং তদ্বিপরীত হয়। আমার অসম্ভব বিষয়টিকে সমর্থন করে অসম্ভব নয়, তবে যথেষ্ট সংশ্লেষিত।
এলজেঞ্জো

1

যেমন ইতিমধ্যে এখানে বলা হয়েছে সিঙ্ক্রোনাইজড ব্লকটি ব্যবহারকারী-সংজ্ঞায়িত ভেরিয়েবলটিকে লক অবজেক্ট হিসাবে ব্যবহার করতে পারে, যখন সিঙ্ক্রোনাইজড ফাংশনটি কেবল "এটি" ব্যবহার করে। এবং অবশ্যই আপনি নিজের ফাংশনগুলির ক্ষেত্রগুলির সাথে ম্যানিপুলেট করতে পারেন যা সিঙ্ক্রোনাইজ করা উচিত এবং এগুলি।

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

পার্থক্যটির আরও বিশদ বিবরণ আপনি এখানে পেতে পারেন: http://www.artima.com/insidejvm/ed2/threadsynchP.html

এছাড়াও নিম্নলিখিত দৃষ্টিকোণের কারণে সিঙ্ক্রোনাইজড ব্লকের ব্যবহার ভাল নয়:

সিঙ্ক্রোনাইজড কীওয়ার্ডটি একটি অঞ্চলে খুব সীমাবদ্ধ: একটি সিঙ্ক্রোনাইজড ব্লক থেকে বেরিয়ে আসার সময়, সেই লকের জন্য অপেক্ষা করা সমস্ত থ্রেড অবশ্যই অবরুদ্ধ করা উচিত, তবে এই থ্রেডগুলির মধ্যে একটি মাত্র লকটি নিতে পারে; অন্য সমস্ত লোকেরা দেখতে পায় যে লকটি নেওয়া হয়েছে এবং আবার অবরুদ্ধ অবস্থায় ফিরে যায়। এটি কেবল প্রচুর নষ্ট প্রক্রিয়াচক্র নয়: প্রায়শই একটি থ্রেড আনলক করতে প্রসঙ্গের স্যুইচটিতে ডিস্কটি বন্ধ করে দেওয়া মেমরিও জড়িত থাকে এবং এটি খুব, খুব ব্যয়বহুল।

এই ক্ষেত্রের আরও তথ্যের জন্য আমি আপনাকে এই নিবন্ধটি পড়ার পরামর্শ দিচ্ছি: http://java.dzone.com/articles/synchronized-considered


1

এটি অন্য উত্তরগুলির জন্য কেবলমাত্র পরিপূরক, তবে যদি লকিংয়ের জন্য ব্যক্তিগত বিষয়গুলি ব্যবহার করার ক্ষেত্রে আপনার প্রধান আপত্তিটি হ'ল এটি আপনার শ্রেণীর সাথে ব্যবসায় যুক্তির সাথে সম্পর্কিত নয় এমন ক্ষেত্রগুলি নিয়ে বিশৃঙ্খলা @Synchronizedসৃষ্টি করে তবে প্রজেক্ট লম্বোককে সংকলন-সময় বয়লারপ্লেট উত্পন্ন করতে হবে:

@Synchronized
public int foo() {
    return 0;
}

সংকলন

private final Object $lock = new Object[0];

public int foo() {
    synchronized($lock) {
        return 0;
    }
}

0

সিঙ্ক্রোনাইজড (এটি) ব্যবহারের জন্য একটি ভাল উদাহরণ।

// add listener
public final synchronized void addListener(IListener l) {listeners.add(l);}
// remove listener
public final synchronized void removeListener(IListener l) {listeners.remove(l);}
// routine that raise events
public void run() {
   // some code here...
   Set ls;
   synchronized(this) {
      ls = listeners.clone();
   }
   for (IListener l : ls) { l.processEvent(event); }
   // some code here...
}

আপনি এখানে দেখতে পাচ্ছেন, আমরা কয়েকটি সিঙ্ক্রোনাইজড পদ্ধতিতে দৈর্ঘ্যের (সম্ভবত রান পদ্ধতির অসীম লুপ) সহজ সহযোগিতা করতে এটিতে সিঙ্ক্রোনাইজ ব্যবহার করি।

অবশ্যই এটি ব্যক্তিগত ক্ষেত্রে সিঙ্ক্রোনাইজড ব্যবহার করে খুব সহজেই নতুন করে লেখা যেতে পারে। তবে কখনও কখনও, যখন আমাদের ইতিমধ্যে সিঙ্ক্রোনাইজড পদ্ধতিগুলির সাথে কিছু নকশা থাকে (যেমন লিগ্যাসি ক্লাস হয়, তখন আমরা সিঙ্ক্রোনাইজ করা (এটি) একমাত্র সমাধান হতে পারে)।


যে কোনও বস্তু এখানে লক হিসাবে ব্যবহার করা যেতে পারে। এটি হওয়ার দরকার নেই this। এটি একটি ব্যক্তিগত ক্ষেত্র হতে পারে।
ফিনউইউ

সঠিক, তবে এই উদাহরণটির উদ্দেশ্যটি ছিল কীভাবে সঠিক সিনক্রোনাইজ করা যায় তা দেখানো, যদি আমরা পদ্ধতি সিঙ্ক্রোনাইজেশন ব্যবহার করার সিদ্ধান্ত নিই।
বার্ট প্রোকপ

0

এটি আপনি যে কাজটি করতে চান তার উপর নির্ভর করে তবে আমি এটি ব্যবহার করব না। এছাড়াও, পরীক্ষা করতে চান যে থ্রেড-সেভ-নেসটি আপনি সম্পন্ন করতে চান তা প্রথম স্থানে সিঙ্ক্রোনাইজ করে (এটি) করা যায় না? এপিআইতে কিছু দুর্দান্ত লক রয়েছে যা আপনাকে সাহায্য করতে পারে :)


0

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

// Synchronization objects (locks)
private static HashMap<String, Object> locks = new HashMap<String, Object>();
// Simple method
private static Object atomic() {
    StackTraceElement [] stack = Thread.currentThread().getStackTrace(); // get execution point 
    StackTraceElement exepoint = stack[2];
    // creates unique key from class name and line number using execution point
    String key = String.format("%s#%d", exepoint.getClassName(), exepoint.getLineNumber()); 
    Object lock = locks.get(key); // use old or create new lock
    if (lock == null) {
        lock = new Object();
        locks.put(key, lock);
    }
    return lock; // return reference to lock
}
// Synchronized code
void dosomething1() {
    // start commands
    synchronized (atomic()) {
        // atomic commands 1
        ...
    }
    // other command
}
// Synchronized code
void dosomething2() {
    // start commands
    synchronized (atomic()) {
        // atomic commands 2
        ...
    }
    // other command
}

0

synchronized(this)লকিং প্রক্রিয়া হিসাবে ব্যবহার করা থেকে বিরত থাকুন: এটি পুরো শ্রেণীর উদাহরণটি লক করে এবং অচলাবস্থার কারণ হতে পারে। এই ধরনের ক্ষেত্রে, কেবলমাত্র একটি নির্দিষ্ট পদ্ধতি বা পরিবর্তনশীল লক করার কোডটি রিফ্যাক্টর করে, পুরো ক্লাসটি লক হয় না। Synchronisedপদ্ধতি স্তর ভিতরে ব্যবহার করা যেতে পারে।
ব্যবহারের পরিবর্তে synchronized(this), নীচের কোডটি দেখায় যে কীভাবে আপনি কেবল একটি পদ্ধতি লক করতে পারেন।

   public void foo() {
if(operation = null) {
    synchronized(foo) { 
if (operation == null) {
 // enter your code that this method has to handle...
          }
        }
      }
    }

0

2019 সালে আমার দুটি সেন্ট যদিও এই প্রশ্নটি ইতিমধ্যে নিষ্পত্তি হতে পারে।

আপনি কী করছেন তা যদি আপনি জানেন তবে 'এটি' তে লক করা খারাপ নয় তবে 'এই' এ লক করা দৃশ্যের পিছনে রয়েছে (যা দুর্ভাগ্যক্রমে পদ্ধতির সংজ্ঞাতে সংলগ্ন কীওয়ার্ডটি মঞ্জুরি দেয়)।

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

আরও বিশদটি জানাতে, বিপরীতে আপনাকে অবশ্যই জানতে হবে যে আপনি অ্যাক্সেসযোগ্য লকটিতে লক (যদি আপনার লকটি কেউ 'চুরি' করতে পারে না, আপনি সম্পূর্ণ নিয়ন্ত্রণে থাকেন) তবে আপনি কী 'লাভ' করছেন (বা 'হারাচ্ছেন')। ..)।

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

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

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

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

দ্রষ্টব্য 1: আমি জানি যে আপনি সুস্পষ্ট লক অবজেক্টটি ব্যবহার করে এবং এটি প্রকাশ করে সিঙ্ক্রোনাইজ করা (এটি) 'অর্জন' যাইহোক অর্জন করতে পারেন তবে আমি মনে করি যে আপনার আচরণটি যদি ভালভাবে নথিভুক্ত হয় এবং আপনি আসলে 'এটি'র লকিংয়ের অর্থ কী তা আপনি জানেন।

দ্রষ্টব্য 2: আমি এই যুক্তিটির সাথে একমত নই যে কোনও কোড যদি দুর্ঘটনাক্রমে আপনার লকটি চুরি করে তবে এটি একটি বাগ সমাধান করতে হবে। এটি একরকম একই যুক্তি হিসাবে বলার মতো যে আমি আমার সমস্ত পদ্ধতিগুলি জনসাধারণ হিসাবে বোঝানো না হলেও এমনকি সর্বজনীন করতে পারি। যদি কেউ 'দুর্ঘটনাক্রমে' আমার ব্যক্তিগত উদ্দেশ্যে ব্যক্তিগত উদ্দেশ্য হিসাবে অভিহিত করা হয় তবে এটি একটি বাগ। এই দুর্ঘটনাটিকে প্রথম স্থানে সক্ষম করুন কেন !!! আপনার লক চুরি করার ক্ষমতা যদি আপনার শ্রেণীর জন্য সমস্যা হয় তবে এটির অনুমতি দিন না। এর মত সহজ.


-3

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

এটি পাথর নিক্ষেপ করা হয় না, এটি বেশিরভাগ ভাল অনুশীলন এবং ত্রুটি প্রতিরোধের একটি সমস্যা।

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