আমি জাভাতে মাল্টি-থ্রেডিং পড়ছিলাম এবং আমি এটি জুড়ে এসেছি
স্থানীয় ভেরিয়েবলগুলি জাভায় থ্রেড নিরাপদ।
সেই থেকে আমি ভাবছিলাম যে কীভাবে / কেন স্থানীয় ভেরিয়েবলগুলি থ্রেড নিরাপদ।
কেউ দয়া করে আমাকে জানাতে পারেন?
আমি জাভাতে মাল্টি-থ্রেডিং পড়ছিলাম এবং আমি এটি জুড়ে এসেছি
স্থানীয় ভেরিয়েবলগুলি জাভায় থ্রেড নিরাপদ।
সেই থেকে আমি ভাবছিলাম যে কীভাবে / কেন স্থানীয় ভেরিয়েবলগুলি থ্রেড নিরাপদ।
কেউ দয়া করে আমাকে জানাতে পারেন?
উত্তর:
আপনি যখন একটি থ্রেড তৈরি করবেন তখন এটির নিজস্ব স্ট্যাক তৈরি হবে। দুটি থ্রেডে দুটি স্ট্যাক থাকবে এবং একটি থ্রেড এর স্ট্যাকটি অন্য থ্রেডের সাথে ভাগ করে না।
আপনার প্রোগ্রামে সংজ্ঞায়িত সমস্ত স্থানীয় ভেরিয়েবলগুলি স্ট্যাকের মধ্যে মেমরি বরাদ্দ করা হবে (যতীন মন্তব্য করেছেন, মেমরির অর্থ এখানে, বস্তুর জন্য রেফারেন্স-মান এবং আদিম ধরণের মূল্য) (একটি থ্রেডের মাধ্যমে প্রতিটি পদ্ধতি কল তার নিজস্ব স্ট্যাকের উপর একটি স্ট্যাক ফ্রেম তৈরি করে)। এই থ্রেড দ্বারা পদ্ধতি প্রয়োগের কাজ শেষ হওয়ার সাথে সাথে স্ট্যাক ফ্রেমটি সরানো হবে।
ইউটিউবে স্ট্যানফোর্ডের অধ্যাপকের দুর্দান্ত বক্তৃতা রয়েছে যা আপনাকে এই ধারণাটি বুঝতে সহায়তা করতে পারে।
স্থানীয় ভেরিয়েবলগুলি প্রতিটি থ্রেডের নিজস্ব স্ট্যাকে সংরক্ষণ করা হয়। এর অর্থ হ'ল স্থানীয় ভেরিয়েবলগুলি থ্রেডের মাঝে কখনই ভাগ করা যায় না। এর অর্থ হ'ল সমস্ত স্থানীয় আদিম পরিবর্তনশীল থ্রেড নিরাপদ safe
public void someMethod(){
long threadSafeInt = 0;
threadSafeInt++;
}
বস্তুর স্থানীয় উল্লেখগুলি কিছুটা আলাদা। রেফারেন্স নিজেই ভাগ করা হয় না। তবে রেফারেন্স করা অবজেক্টটি প্রতিটি থ্রেডের স্থানীয় স্ট্যাকের মধ্যে সংরক্ষণ করা হয় না। সমস্ত অবজেক্টগুলি শেয়ারড হিপগুলিতে সঞ্চিত থাকে। স্থানীয়ভাবে তৈরি কোনও বস্তু যদি এটি তৈরি করা পদ্ধতিটি থেকে কখনই পলায়ন না করে তবে এটি থ্রেড নিরাপদ। প্রকৃতপক্ষে আপনি এটিকে অন্যান্য পদ্ধতি এবং অবজেক্টগুলিতেও প্রেরণ করতে পারবেন যতক্ষণ না এই পদ্ধতি বা অবজেক্টগুলির কোনওটিই পাস করা বস্তুকে অন্য থ্রেডে উপলব্ধ না করে
কার্যকারিতা সংজ্ঞা মত পদ্ধতি সম্পর্কে চিন্তা করুন। যখন দুটি থ্রেড একই পদ্ধতি চালায়, তারা কোনওভাবেই সম্পর্কিত হয় না। তারা প্রত্যেকে স্থানীয় স্থানীয় চলকটির নিজস্ব সংস্করণ তৈরি করবে এবং কোনওভাবেই একে অপরের সাথে ইন্টারঅ্যাক্ট করতে সক্ষম হবে না।
যদি ভেরিয়েবলগুলি স্থানীয় না হয় (যেমন শ্রেণীর স্তরের কোনও পদ্ধতির বাইরে উদাহরণস্বরূপ ভেরিয়েবলগুলি সংজ্ঞায়িত করা হয়), তবে সেগুলি দৃষ্টান্তের সাথে সংযুক্ত থাকে (কোনও পদ্ধতির একক রানের সাথে নয়)। এই ক্ষেত্রে একই পদ্ধতিতে চলমান দুটি থ্রেড উভয়ই একটি পরিবর্তনশীল দেখতে পান এবং এটি থ্রেড-নিরাপদ নয়।
এই দুটি ক্ষেত্রে বিবেচনা করুন:
public class NotThreadsafe {
int x = 0;
public int incrementX() {
x++;
return x;
}
}
public class Threadsafe {
public int getTwoTimesTwo() {
int x = 1;
x++;
return x*x;
}
}
প্রথমটিতে, একই উদাহরণে চলমান দুটি থ্রেড NotThreadsafe
একই x দেখতে পাবে। এটি বিপজ্জনক হতে পারে, কারণ থ্রেডগুলি এক্স পরিবর্তন করার চেষ্টা করছে! দ্বিতীয়টিতে, একই উদাহরণে চলমান দুটি থ্রেড Threadsafe
সম্পূর্ণ ভিন্ন পরিবর্তনশীল দেখতে পাবে এবং একে অপরকে প্রভাবিত করতে পারে না।
প্রতিটি পদ্ধতির অনুরোধের নিজস্ব স্থানীয় ভেরিয়েবল থাকে এবং স্পষ্টতই, একটি পদ্ধতির অনুরোধটি একটি থ্রেডে ঘটে। একটি পরিবর্তনশীল যা কেবলমাত্র একটি একক থ্রেড দ্বারা আপডেট করা অন্তর্নিহিত থ্রেড-নিরাপদ।
তবে এর দ্বারা কী বোঝানো হয়েছে তার দিকে নজর রাখুন: কেবলমাত্র ভেরিয়েবলের লেখকই থ্রেড-নিরাপদ; যে বিষয়টিকে এটি নির্দেশ করে সেগুলিতে কল করার পদ্ধতিগুলি সহজাতভাবে থ্রেড-নিরাপদ নয় । একই জিনিস অবজেক্টের ভেরিয়েবলগুলি আপডেট করার জন্য যায়।
নাম্বারীর মতো উত্তরগুলি ছাড়াও।
আমি উল্লেখ করতে চাই যে আপনি অ্যানয়মাস টাইপ পদ্ধতিতে একটি স্থানীয় ভেরিয়েবল ব্যবহার করতে পারেন:
এই পদ্ধতিটি অন্যান্য থ্রেডগুলিতে ডেকে আনা যেতে পারে যা থ্রেডসফিটির সাথে আপস করতে পারে, তাই জাভা ব্যাহত ধরনেরগুলিতে ব্যবহৃত সমস্ত স্থানীয় ভেরিয়েবলকে চূড়ান্ত হিসাবে ঘোষণা করতে বাধ্য করে।
এই অবৈধ কোড বিবেচনা করুন:
public void nonCompilableMethod() {
int i=0;
for(int t=0; t<100; t++)
{
new Thread(new Runnable() {
public void run() {
i++; //compile error, i must be final:
//Cannot refer to a non-final variable i inside an
//inner class defined in a different method
}
}).start();
}
}
যদি জাভা এটি অনুমতি দেয় (যেমন সি # "ক্লোজার্স" এর মাধ্যমে করে), একটি স্থানীয় ভেরিয়েবল আর সব পরিস্থিতিতে থ্রেডসেফ হবে না। এই ক্ষেত্রে, i
সমস্ত থ্রেডের শেষে মানটির গ্যারান্টি নেই 100
।
থ্রেডের নিজস্ব স্ট্যাক থাকবে। দুটি থ্রেডে দুটি স্ট্যাক থাকবে এবং একটি থ্রেড এর স্ট্যাকটি অন্য থ্রেডের সাথে ভাগ করে না। স্থানীয় ভেরিয়েবলগুলি প্রতিটি থ্রেডের নিজস্ব স্ট্যাকে সংরক্ষণ করা হয়। এর অর্থ হ'ল স্থানীয় ভেরিয়েবলগুলি থ্রেডের মাঝে কখনই ভাগ করা যায় না।
মূলত শ্রেণীর তথ্য এবং ডেটা সঞ্চয় করার জন্য জাভাতে চার ধরণের স্টোরেজ রয়েছে:
পদ্ধতির ক্ষেত্র, গাদা, জাভা স্ট্যাক, পিসি
সুতরাং মেথড এরিয়া এবং হিপগুলি সমস্ত থ্রেড দ্বারা ভাগ করা হয়েছে তবে প্রতিটি থ্রেডের নিজস্ব জাভা স্ট্যাক এবং পিসি রয়েছে এবং এটি অন্য কোনও থ্রেড দ্বারা ভাগ করা যায় না।
জাভা প্রতিটি পদ্ধতি স্ট্যাক ফ্রেম হিসাবে হয়। সুতরাং, যখন কোনও পদ্ধতিকে একটি থ্রেড দ্বারা ডাকা হয় যে স্ট্যাক ফ্রেমটি তার জাভা স্ট্যাকের উপর লোড করা হয় A সমস্ত স্থানীয় ভেরিয়েবল যা ack স্ট্যাক ফ্রেমে রয়েছে এবং সম্পর্কিত অপারেন্ড স্ট্যাক অন্যরা ভাগ করে নি। পদ্ধতির বাইট কোড সম্পাদন করার জন্য পিসির কাছে পরবর্তী নির্দেশনার তথ্য থাকবে। সুতরাং সমস্ত স্থানীয় ভেরিয়েবলগুলি থ্রেড নিরাপদ।
@ ওয়েস্টনও ভাল উত্তর দিয়েছে।
থ্রেড স্ট্যাকের মধ্যে কেবল স্থানীয় ভেরিয়েবলগুলি সংরক্ষণ করা হয়।
স্থানীয় পরিবর্তনশীল যা primitive type
(যেমন int, দীর্ঘ ...) এতে সঞ্চিত থাকে thread stack
এবং ফলস্বরূপ - অন্যান্য থ্রেডে এটির অ্যাক্সেস নেই।
স্থানীয় পরিবর্তনশীল যা reference type
(এর উত্তরসূরি Object
) 2 অংশ থেকে থাকে - ঠিকানা (যা এতে সঞ্চিত থাকে thread stack
) এবং অবজেক্ট (যা এতে সঞ্চিত থাকে heap
)
class MyRunnable implements Runnable() {
public void run() {
method1();
}
void method1() {
int intPrimitive = 1;
method2();
}
void method2() {
MyObject1 myObject1 = new MyObject1();
}
}
class MyObject1 {
MyObject2 myObject2 = new MyObject2();
}
class MyObject2 {
MyObject3 myObject3 = MyObject3.shared;
}
class MyObject3 {
static MyObject3 shared = new MyObject3();
boolean b = false;
}