স্ট্যাটিক ভেরিয়েবলগুলি থ্রেডগুলির মধ্যে ভাগ করা আছে?


95

থ্রেডিংয়ের বিষয়ে উচ্চ স্তরের জাভা ক্লাসে আমার শিক্ষক এমন কিছু বলেছেন যা সম্পর্কে আমি নিশ্চিত নই।

তিনি বলেছিলেন যে নিম্নলিখিত কোডগুলি অগত্যা readyপরিবর্তনশীলটিকে আপডেট করবে না । তাঁর মতে, দুটি থ্রেড অগত্যা স্ট্যাটিক ভেরিয়েবল ভাগ করে না, বিশেষত যখন প্রতিটি থ্রেড (মূল থ্রেড বনাম ReaderThread) তার নিজস্ব প্রসেসরে চলছে এবং সুতরাং একই রেজিস্টার / ক্যাশে / ইত্যাদি ভাগ করে না এবং একটি সিপিইউ করে অন্য আপডেট করবেন না।

মূলত, তিনি বলেছিলেন যে readyমূল থ্রেডে এটি আপডেট করা সম্ভব , তবে এতে নেই ReaderThread, যাতে ReaderThreadঅসীম লুপ হয়ে যায়।

তিনি দাবি করেছিলেন যে প্রোগ্রামটি মুদ্রণ করা সম্ভব হয়েছিল 0বা 42। আমি বুঝতে পারি কীভাবে 42মুদ্রিত হতে পারে, তবে না 0। তিনি উল্লেখ করেছিলেন যে যখন numberভেরিয়েবলটি ডিফল্ট মানকে সেট করা হয় তখন এটি হবে ।

আমি ভেবেছিলাম সম্ভবত এটি গ্যারান্টিযুক্ত নয় যে থ্রেডগুলির মধ্যে স্ট্যাটিক ভেরিয়েবল আপডেট হয়েছে তবে জাভাটির জন্য এটি আমাকে খুব বিজোড় বলে মনে করে। readyঅস্থির করে তোলে কি এই সমস্যাটিকে সংশোধন করে?

তিনি এই কোডটি দেখিয়েছেন:

public class NoVisibility {  
    private static boolean ready;  
    private static int number;  
    private static class ReaderThread extends Thread {   
        public void run() {  
            while (!ready)   Thread.yield();  
            System.out.println(number);  
        }  
    }  
    public static void main(String[] args) {  
        new ReaderThread().start();  
        number = 42;  
        ready = true;  
    }  
}

স্থানীয়-বহিরাগত ভেরিয়েবলের দৃশ্যমানতা নির্ভর করে না তারা স্ট্যাটিক ভেরিয়েবল, অবজেক্ট ফিল্ড বা অ্যারের উপাদান কিনা, তাদের সবার বিবেচ্যতা একই রকম। (অ্যারে উপাদানগুলিকে অস্থির করে তোলা যায় না এমন সমস্যার সাথে)
ŭ

4
আপনার শিক্ষককে জিজ্ঞাসা করুন যে তিনি কী ধরণের আর্কিটেকচার মনে করেন যে এটি '0' দেখা সম্ভব হবে। তবুও, তত্ত্বের ভিত্তিতে তিনি ঠিক বলেছেন।
বেটসেস

4
@ বেস্টেস এই ধরণের প্রশ্ন জিজ্ঞাসা করা শিক্ষককে প্রকাশ করবে যে তিনি যা বলছিলেন তার পুরো বিষয়টি তিনি মিস করবেন missed মুল বক্তব্যটি হ'ল সক্ষম প্রোগ্রামাররা বুঝতে পারে কোনটি গ্যারান্টিযুক্ত এবং কোনটি নয় এবং গ্যারান্টিযুক্ত নয় এমন কিছুর উপর নির্ভর করে না, কমপক্ষে গ্যারান্টিযুক্ত কী এবং কেন তা সঠিকভাবে না বুঝে না।
ডেভিড শোয়ার্টজ

তারা একই শ্রেণীর লোডার দ্বারা লোড করা সমস্ত কিছুর মধ্যে ভাগ করা হয়। থ্রেড সহ
মার্নকুইস লরনের

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

উত্তর:


75

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

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

এখানে সেই লিঙ্কটির একটি উদ্ধৃতি (জেড ওয়েসলি-স্মিথের মন্তব্যে সরবরাহ করা হয়েছে):

জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশনের ১ Chapter তম অধ্যায় মেমরি অপারেশনের ক্ষেত্রে ঘটে যাওয়া সম্পর্কের সংজ্ঞা দেয় যেমন ভাগ করা ভেরিয়েবলগুলি পড়ে এবং লেখায় reads একটি থ্রেড দ্বারা লেখার ফলাফলগুলি গ্যারান্টিযুক্ত যে কেবল অন্য থ্রেড দ্বারা পঠনযোগ্য তবেই লেখার ক্রিয়াকলাপ ঘটে-পঠন অপারেশনের আগে। সিঙ্ক্রোনাইজড এবং অস্থির গঠন, পাশাপাশি থ্রেড.স্টার্ট () এবং থ্রেড.জোঁইন () পদ্ধতিগুলি সম্পর্কের আগে ঘটতে পারে। নির্দিষ্টভাবে:

  • একটি থ্রেডের প্রতিটি ক্রিয়াকলাপ ঘটে that থ্রেডের প্রতিটি ক্রিয়নের আগে যা প্রোগ্রামের ক্রমে আসে।

  • একই মনিটরের প্রতিটি পরবর্তী লক (সিঙ্ক্রোনাইজড ব্লক বা পদ্ধতি প্রবেশ) এর আগে একটি মনিটরের একটি আনলক (সিঙ্ক্রোনাইজড ব্লক বা পদ্ধতি প্রস্থান) ঘটে। এবং ঘটনার আগে সম্পর্কটি ট্রানজিটিভ হওয়ার কারণে, আনলক হওয়ার আগে কোনও থ্রেডের সমস্ত ক্রিয়াকলাপ - সমস্ত ক্রিয়াকলাপের পরে মনিটরের যে কোনও থ্রেড লক করা হয়।

  • একটি অস্থির ক্ষেত্রের একটি লিখন ঘটে happens একই ক্ষেত্রের প্রতিটি পরবর্তী পাঠের আগে। অস্থির ক্ষেত্রগুলি লিখতে এবং পড়তে মনিটরে প্রবেশ এবং প্রস্থান করার মতো মেমরির ধারাবাহিকতা প্রভাব থাকে, তবে পারস্পরিক বর্জনীয় লককে আবদ্ধ করে না।

  • কোনও থ্রেড শুরু করার জন্য কল আসে - শুরু করা থ্রেডের কোনও ক্রিয়াকলাপের আগে।

  • কোনও থ্রেডের সমস্ত ক্রিয়াকলাপ ঘটে যায় - অন্য কোনও থ্রেড সফলভাবে সেই থ্রেডের একটি যোগদান থেকে ফিরে আসার আগে।


4
অনুশীলনে, "একটি সময়োচিত পদ্ধতিতে" এবং "সদা" সমার্থক শব্দ। উপরের কোডটি কখনই শেষ না করা খুব সম্ভব।
তিনি TREE

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

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

4
"যদি না আপনি অস্থিতিশীল কীওয়ার্ড ব্যবহার করেন বা সিঙ্ক্রোনাইজ করেন না" " "লেখক এবং পাঠকের মধ্যে কোনও প্রাসঙ্গিক সম্পর্ক না হওয়ার আগে" এবং এই লিঙ্কটি পড়তে হবে: download.oracle.com/javase/6/docs/api/java/util/concurrent/…
জেদ ওয়েসলি-স্মিথ

4
@ বেসস্টেস ভাল দাগযুক্ত। দুর্ভাগ্যক্রমে থ্রেডগ্রুপটি বিভিন্ন উপায়ে ভাঙা।
জেদ ওয়েসলি-স্মিথ

37

তিনি দৃশ্যমানতার বিষয়ে কথা বলছিলেন এবং খুব আক্ষরিকভাবে নেওয়া উচিত নয়।

স্ট্যাটিক ভেরিয়েবলগুলি প্রকৃতপক্ষে থ্রেডগুলির মধ্যে ভাগ করা হয় তবে এক থ্রেডে করা পরিবর্তনগুলি অন্য থ্রেডের সাথে সাথে তত্ক্ষণাত দৃশ্যমান নাও হতে পারে, দেখে মনে হয় ভেরিয়েবলের দুটি অনুলিপি রয়েছে।

এই নিবন্ধটিতে এমন একটি দৃশ্য উপস্থাপন করা হয়েছে যা তিনি তথ্য উপস্থাপনের সাথে সামঞ্জস্যপূর্ণ:

প্রথমে আপনাকে জাভা মেমরির মডেল সম্পর্কে কিছুটা বুঝতে হবে। আমি সংক্ষিপ্তভাবে এবং ভাল ব্যাখ্যা করতে কয়েক বছর ধরে কিছুটা সংগ্রাম করেছি। আজকের হিসাবে, আমি এটি বর্ণনা করার জন্য সবচেয়ে ভাল উপায়টি মনে করতে পারি যদি আপনি এটি এইভাবে কল্পনা করেন:

  • জাভাতে প্রতিটি থ্রেড পৃথক মেমরি স্পেসে স্থান নেয় (এটি স্পষ্টত অসত্য, সুতরাং এটি আমার সাথে সহ্য করুন)।

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

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

...

থ্রেড মডেল

তবে আবার, থ্রেডিং এবং অস্থির সম্পর্কে চিন্তা করার জন্য এটি কেবল একটি মানসিক মডেল, জেভিএম কীভাবে কাজ করে তা নয়।


12

মূলত এটি সত্য, তবে আসলে সমস্যাটি আরও জটিল। ভাগ করা ডেটার দৃশ্যমানতা কেবল সিপিইউ ক্যাশে দ্বারা নয়, নির্দেশাবলীর বহিরাগত অর্ডার প্রয়োগের দ্বারাও প্রভাবিত হতে পারে।

সুতরাং জাভা একটি মেমোরি মডেল সংজ্ঞায়িত করে , তাতে বলা হয় যে কোন পরিস্থিতিতে থ্রেডগুলি ভাগ করা ডেটার ধারাবাহিক অবস্থা দেখতে পাবে।

আপনার বিশেষ ক্ষেত্রে, volatileদৃশ্যমানতার গ্যারান্টি যুক্ত করা ।


8

তারা অবশ্যই "ভাগ করা" এই অর্থে যে তারা উভয়ই একই ভেরিয়েবলকে বোঝায় তবে তারা একে অপরের আপডেটগুলি অগত্যা দেখতে পাবে না। এটি কেবল স্থির নয়, কোনও পরিবর্তনশীলের জন্য সত্য।

এবং তাত্ত্বিকভাবে, অন্য থ্রেড দ্বারা রচিত লেখাগুলি ভিন্ন ক্রমে উপস্থিত হতে পারে, যদি না ভেরিয়েবলগুলি ঘোষিত না হয় volatileবা লেখকগুলি সুস্পষ্টভাবে সিঙ্ক্রোনাইজ না হয়।


5

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


2

আপনি যখন স্ট্যাটিক আদিম ধরণের ভেরিয়েবল জাভা ডিফল্ট শুরু করেন তখন স্ট্যাটিক ভেরিয়েবলের জন্য একটি মান নির্ধারণ করে

public static int i ;

আপনি যখন ভেরিয়েবলটিকে এই জাতীয় i = 0 এর ডিফল্ট মান হিসাবে নির্ধারণ করেন; আপনাকে কেন 0 পাওয়ার সম্ভাবনা রয়েছে তা স্থির করে তারপরে মূল থ্রেডটি বুলিয়ান প্রস্তুতের মানটিকে সত্য বলে আপডেট করে। যেহেতু প্রস্তুত হ'ল স্থির পরিবর্তনশীল, মূল থ্রেড এবং একই মেমরি ঠিকানার অন্য থ্রেড রেফারেন্স তাই প্রস্তুত ভেরিয়েবল পরিবর্তন। সুতরাং গৌণ থ্রেডটি লুপ এবং মুদ্রণের মানটি থেকে বেরিয়ে আসে। মুদ্রণের সময় সংখ্যার মান প্রারম্ভিক মান 0 হয় যদি মূল থ্রেড আপডেট নম্বর ভেরিয়েবলের আগে লুপের সময় থ্রেড প্রক্রিয়াটি শেষ হয়ে যায়। তারপরে 0 মুদ্রণের সম্ভাবনা রয়েছে


-2

@ ডোনটোকসটা আপনি আপনার শিক্ষক এবং স্কুলে তাকে আবার যেতে পারেন :)

বাস্তব বিশ্বের কয়েকটি নোট এবং আপনি যা দেখেন বা যা বলে তা নির্বিশেষে। দয়া করে নোট করুন, নীচের শব্দগুলি সঠিকভাবে প্রদর্শিত ক্রমে এই বিশেষ ক্ষেত্রে সম্পর্কিত।

নিম্নলিখিত 2 ভেরিয়েবলটি কার্যত কোনও জেনে রাখা স্থাপত্যের আওতায় একই ক্যাশে লাইনে থাকবে।

private static boolean ready;  
private static int number;  

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

শুরু করা থ্রেড ReaderThreadপ্রক্রিয়াটি বাঁচিয়ে রাখতে চলেছে কারণ এটি কোনও ডেমন নয়! সুতরাং readyএবং numberএকসাথে ফ্লাশ করা হবে (বা কোনও প্রসঙ্গের সুইচ দেখা দিলে তার আগে সংখ্যা) এবং এই ক্ষেত্রে পুনর্নির্মাণের কোনও আসল কারণ নেই কমপক্ষে আমি এমনকি তার একটিও ভাবতে পারি না। কিছুই দেখতে আপনার সত্যিকারের অদ্ভুত কিছু প্রয়োজন হবে 42। আবার আমি ধরে নিচ্ছি উভয় স্ট্যাটিক ভেরিয়েবল একই ক্যাশে লাইনে থাকবে। আমি কেবল 4 বাইট লম্বা বা একটি জেভিএম ক্যাশে লাইনটি কল্পনা করতে পারি না যা এগুলি একটি অবিচ্ছিন্ন অঞ্চলে (ক্যাশে লাইন) বরাদ্দ করবে না।


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

4
আমি বলেছিলাম যে এটি অনুমানটি অনুসরণ করে না, তবে একজন শিক্ষক হিসাবে কমপক্ষে একটি উপযুক্ত উদাহরণ খুঁজে পান যা বাস্তবে কিছু পণ্য আর্কিটেকচারে ব্যর্থ হতে পারে, সুতরাং উদাহরণটি যথাযথ।
বেটসেস

6
সম্ভবত আমি থ্রেড-নিরাপদ কোড লেখার জন্য সবচেয়ে খারাপ পরামর্শ।
লরেন্স ডল

4
@ বেস্টেস: আপনার প্রশ্নের সহজ উত্তরটি হ'ল এই: "নির্দিষ্টকরণ এবং নথির কোড, আপনার নির্দিষ্ট সিস্টেম বা প্রয়োগের পার্শ্ব প্রতিক্রিয়া নয়"। অন্তর্নিহিত হার্ডওয়্যারটির অজ্ঞাব্য নকশাকৃত ডিজাইন করা ভার্চুয়াল-মেশিন প্ল্যাটফর্মে এটি বিশেষত গুরুত্বপূর্ণ।
লরেন্স ডল

4
@ বেস্টেস: শিক্ষকগণের বক্তব্যটি হ'ল (ক) কোডটি পরীক্ষা করার সময় ভালভাবে কাজ করতে পারে এবং (খ) কোডটি নষ্ট হয়ে গেছে কারণ এটি হার্ডওয়্যার অপারেশনের উপর নির্ভর করে, নকশার গ্যারান্টি নয়। মুল বক্তব্যটি হ'ল মনে হচ্ছে এটি ঠিক আছে, তবে এটি ঠিক নেই।
লরেন্স ডল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.