এটি বোঝা গুরুত্বপূর্ণ যে থ্রেড সুরক্ষার দুটি দিক রয়েছে।
- সম্পাদন নিয়ন্ত্রণ, এবং
- মেমরি দৃশ্যমানতা
প্রথমটি কোড সম্পাদন করার সময় নিয়ন্ত্রণ (যখন নির্দেশাবলী কার্যকর করা হয় সেই আদেশ সহ) এবং এটি একযোগে কার্যকর করা যায় কিনা এবং দ্বিতীয়টি যখন করা হয়েছে তার স্মৃতিতে প্রভাবগুলি অন্য থ্রেডে দৃশ্যমান হয় তখন কী করা উচিত। যেহেতু প্রতিটি সিপিইউতে এটির এবং প্রধান মেমোরির মধ্যে কয়েকটি স্তরের ক্যাশ থাকে, বিভিন্ন সিপিইউ বা কোরগুলিতে চলমান থ্রেডগুলি যে কোনও মুহুর্তে সময়ের সাথে "মেমরি" আলাদাভাবে দেখতে পারে কারণ থ্রেডগুলি মূল মেমোরির ব্যক্তিগত কপিগুলি প্রাপ্ত এবং কাজ করার অনুমতিপ্রাপ্ত।
ব্যবহার synchronized
মনিটর (অথবা লক) প্রাপ্তির থেকে আটকায় অন্য কোন থ্রেড একই বস্তুর জন্য , যার ফলে সমস্ত কোড ব্লক সিঙ্ক্রোনাইজেশন দ্বারা সুরক্ষিত প্রতিরোধ একই বস্তুর উপর একই সময়ে নির্বাহ করেন। সিংক্রোনাইজ এছাড়াও সৃষ্টি একটি "ঘটবে-পূর্বে" মেমরি বাধা, একটি মেমরি দৃশ্যমানতা বাধ্যতা কিছু বিন্দু থেকে একটি লক কিছু থ্রেড রিলিজ আপ করা যেমন যে ঘটাচ্ছে মনে হচ্ছে, অন্য থ্রেড পরবর্তীকালে অর্জন করতে একই লক আগেই লক অর্জিত ঘটে থাকতে হবে। ব্যবহারিক শর্তে, বর্তমান হার্ডওয়্যারে, এটি সাধারণত মনিটর অধিগ্রহণ করা হয় এবং সিপিইউ ক্যাশেগুলি ফ্ল্যাশ করার কারণ হয়ে থাকে এবং প্রকাশিত হলে প্রধান মেমোরিতে লেখায়, উভয়ই (তুলনামূলক) ব্যয়বহুল।
volatile
অন্যদিকে, ব্যবহার করে সমস্ত অ্যাক্সেসগুলি (পড়ুন বা লিখুন )টিকে অস্থির ভেরিয়েবলের মূল স্মৃতিতে ঘটতে বাধ্য করে, কার্যকরভাবে অস্থির ভেরিয়েবলকে সিপিইউ ক্যাশের বাইরে রাখে। এটি কিছু ক্রিয়াকলাপের জন্য দরকারী হতে পারে যেখানে ভেরিয়েবলের দৃশ্যমানতা সঠিক হওয়া এবং অ্যাক্সেসের ক্রমটি গুরুত্বপূর্ণ নয় required ব্যবহার volatile
এছাড়াও চিকিত্সার পরিবর্তন long
এবং double
পারমাণবিক হতে তাদের ব্যবহারের প্রয়োজন; কিছু (পুরানো) হার্ডওয়্যারে এটি লক প্রয়োজন হতে পারে, যদিও আধুনিক modern৪ বিট হার্ডওয়ারে নেই। জাভা 5+ এর জন্য নতুন (জেএসআর -133) মেমরি মডেলের অধীনে, অস্থিরতার শব্দার্থকে মেমরির দৃশ্যমানতা এবং নির্দেশের আদেশের সাথে সম্মতিযুক্ত প্রায় ততই শক্তিশালী করার জন্য শক্তিশালী করা হয়েছে (দেখুন http://www.cs.umd.edu /users/pugh/java/memoryModel/jsr-133-faq.html#volatile)। দৃশ্যমানতার উদ্দেশ্যে, একটি অস্থির ক্ষেত্রের প্রতিটি অ্যাক্সেস অর্ধ সিঙ্ক্রোনাইজের মতো কাজ করে।
নতুন মেমরি মডেলের অধীনে, এটি এখনও সত্য যে উদ্বায়ী ভেরিয়েবলগুলি একে অপরের সাথে পুনরায় সাজানো যায় না। পার্থক্যটি হ'ল চারপাশের সাধারণ ক্ষেত্রের অ্যাক্সেসগুলি পুনরায় অর্ডার করা এখন আর এত সহজ। একটি অস্থির ক্ষেত্রে লিখতে মনিটরের রিলিজের মতো একই মেমরি প্রভাব থাকে এবং একটি অস্থির ক্ষেত্র থেকে পড়া মনিটর অর্জনের মতো একই মেমরির প্রভাব ফেলে। বাস্তবে, কারণ নতুন মেমরি মডেলটি অন্যান্য ক্ষেত্রের প্রবেশাধিকারের সাথে অস্থির ক্ষেত্রের প্রবেশের পুনর্বিন্যাসের উপর কঠোর বাধা স্থাপন করে, উদ্বায়ী বা না, যে কোনও কিছু থ্রেডে দৃশ্যমান ছিল A
যখন এটি অস্থির ক্ষেত্রটিতে লেখার সময় f
থ্রেডে দৃশ্যমান হয় B
যখন এটি পড়ে f
।
- জেএসআর 133 (জাভা মেমোরি মডেল) FAQ
সুতরাং, এখন উভয় ফর্মের মেমরি বাধা (বর্তমান জেএমএমের অধীনে) একটি নির্দেশ পুনর্নির্মাণ বাধা সৃষ্টি করে যা সংকলক বা রান-টাইমকে বাধা পেরিয়ে নির্দেশাবলীর পুনঃ-অর্ডার করতে বাধা দেয়। পুরানো জেএমএম-এ, অস্থির পুনঃ-অর্ডার আটকাতে পারেনি। এটি গুরুত্বপূর্ণ হতে পারে, কারণ মেমোরি বাধা ব্যতীত কেবলমাত্র একমাত্র সীমাবদ্ধতা আরোপ করা হয় যে কোনও নির্দিষ্ট থ্রেডের জন্য কোডের নেট এফেক্টটি একই রকম হয় যদি নির্দেশাবলী কার্যকরভাবে সাজানো হয় যেভাবে তারা প্রদর্শিত হয় উৎস.
অস্থির একটি ব্যবহার একটি ভাগ করা হলেও অপরিবর্তনীয় বস্তুর জন্য ফ্লাইতে পুনরায় তৈরি করা হয়, অন্য অনেকগুলি থ্রেড তাদের সম্পাদন চক্রের একটি নির্দিষ্ট সময়ে অবজেক্টটির রেফারেন্স নিয়ে থাকে। পুনরায় তৈরি হওয়া অবজেক্টটি প্রকাশিত হওয়ার পরে কারও কাছে অন্য থ্রেডগুলির প্রয়োজন হয়, তবে সম্পূর্ণ সিঙ্ক্রোনাইজেশনের অতিরিক্ত ওভারহেডের প্রয়োজন হয় না এবং এটির পরিচারকদের যুক্তি এবং ক্যাশে ফ্লাশিং হয়।
// Declaration
public class SharedLocation {
static public SomeObject someObject=new SomeObject(); // default object
}
// Publishing code
// Note: do not simply use SharedLocation.someObject.xxx(), since although
// someObject will be internally consistent for xxx(), a subsequent
// call to yyy() might be inconsistent with xxx() if the object was
// replaced in between calls.
SharedLocation.someObject=new SomeObject(...); // new object is published
// Using code
private String getError() {
SomeObject myCopy=SharedLocation.someObject; // gets current copy
...
int cod=myCopy.getErrorCode();
String txt=myCopy.getErrorText();
return (cod+" - "+txt);
}
// And so on, with myCopy always in a consistent state within and across calls
// Eventually we will return to the code that gets the current SomeObject.
আপনার পঠন-আপডেট-লেখার প্রশ্নে বিশেষভাবে কথা বলছেন। নিম্নলিখিত অনিরাপদ কোডটি বিবেচনা করুন:
public void updateCounter() {
if(counter==1000) { counter=0; }
else { counter++; }
}
এখন, আপডেটকৌনটার () পদ্ধতিটি আনসক্রোনাইজড দিয়ে দুটি থ্রেড একই সাথে এটি প্রবেশ করতে পারে। যা ঘটতে পারে তার অনেকগুলি অনুমতিগুলির মধ্যে একটি হ'ল থ্রেড -1 পরীক্ষার জন্য == 1000 পরীক্ষা করে এবং এটি সত্য বলে মনে হয় এবং তারপরে স্থগিত করা হয়। তারপরে থ্রেড -2 একই পরীক্ষা করে এবং এটি সত্যও দেখায় এবং স্থগিত করা হয়। তারপরে থ্রেড -1 পুনরায় শুরু হয় এবং 0 এর বিপরীতে সেট করে Then তারপরে থ্রেড -2 পুনরায় শুরু হয় এবং আবার 0 টির সাথে কাউন্টার সেট করে কারণ এটি থ্রেড -1 থেকে আপডেটটি মিস করেছে। থ্রেড স্যুইচিং না ঘটলে এমনকি ঘটতে পারে যেমনটি আমি বর্ণনা করেছি, তবে কেবলমাত্র দুটি পৃথক সিপিইউ কোরে কাউন্টারের দুটি পৃথক ক্যাশে অনুলিপি উপস্থিত ছিল এবং থ্রেডগুলি পৃথক পৃথক কোরে চলেছে। এই বিষয়টির জন্য, একটি থ্রেডের একটি মানতে কাউন্টার থাকতে পারে এবং অন্যটিতে কেবল ক্যাশে দেওয়ার কারণে কিছু সম্পূর্ণ ভিন্ন মানের পাল্টা থাকতে পারে।
এই উদাহরণে যা গুরুত্বপূর্ণ তা হল ভেরিয়েবল কাউন্টারটি মূল মেমরি থেকে ক্যাশে পাঠানো হয়েছিল, ক্যাশে আপডেট হয়েছিল এবং পরে কোনও স্মৃতি বাধা এসেছিল বা যখন অন্য কোনও কিছুর জন্য যখন ক্যাশে মেমরির প্রয়োজন হয়েছিল তখন কেবল অনির্দিষ্ট স্থানে মূল স্মৃতিতে ফিরে লেখা হয়েছিল। কাউন্টার তৈরি করা volatile
এই কোডের থ্রেড-সুরক্ষার জন্য অপর্যাপ্ত, কারণ সর্বাধিক এবং অ্যাসাইনমেন্টের জন্য পরীক্ষাটি পৃথক ক্রিয়াকলাপ, বর্ধন সহ যা অ-পারমাণবিক read+increment+write
মেশিনের নির্দেশাবলীর একটি সেট , যেমন:
MOV EAX,counter
INC EAX
MOV counter,EAX
উদ্বায়ী ভেরিয়েবলগুলি কেবল তখন কার্যকর হয় যখন তাদের উপর সঞ্চালিত সমস্ত ক্রিয়াকলাপগুলি "পারমাণবিক" হয়, যেমন আমার উদাহরণ যেখানে সম্পূর্ণরূপে গঠিত বস্তুর উল্লেখ কেবল পঠিত বা লিখিত হয় (এবং প্রকৃতপক্ষে, সাধারণত এটি কেবলমাত্র একটি বিন্দু থেকে লেখা হয়)। আর একটি উদাহরণ হ'ল একটি অস্থির অ্যারে রেফারেন্স যা অনুলিপি-অনুলিপি তালিকার ব্যাক করে, তবে শর্তটি কেবল রেফারেন্সের স্থানীয় কপি নিয়ে প্রথমে পড়তে হবে।