বাফার্ডইনপ্রীম স্ট্রিম কেন সরাসরি ক্ষেত্রটি ব্যবহারের পরিবর্তে একটি স্থানীয় ভেরিয়েবলে একটি ক্ষেত্র অনুলিপি করে


107

আমি যখন থেকে উত্স কোডটি পড়ি, তখন java.io.BufferedInputStream.getInIfOpen()কেন আমি এটির মতো কোড লিখি তা সম্পর্কে আমি বিভ্রান্ত হই:

/**
 * Check to make sure that underlying input stream has not been
 * nulled out due to close; if not return it;
 */
private InputStream getInIfOpen() throws IOException {
    InputStream input = in;
    if (input == null)
        throw new IOException("Stream closed");
    return input;
}

ফিল্ড ভেরিয়েবলটি inসরাসরি নীচের মতো ব্যবহারের পরিবর্তে কেন এটি ব্যবহার করা হচ্ছে:

/**
 * Check to make sure that underlying input stream has not been
 * nulled out due to close; if not return it;
 */
private InputStream getInIfOpen() throws IOException {
    if (in == null)
        throw new IOException("Stream closed");
    return in;
}

কেউ কি যুক্তিসঙ্গত ব্যাখ্যা দিতে পারেন?


ইন Eclipse, আপনি কোনও ifবিবৃতিতে কোনও ডিবাগার থামাতে পারবেন না । সেই উরফ ভেরিয়েবলের কারণ হতে পারে। ঠিক আছে যে নিক্ষেপ করতে চেয়েছিলেন। আমি অনুমান অবশ্যই।
ডিবোস্মিত রায় ২

@ ডিবোস্মিতরে: সত্যিই কি ifবিবৃতিতে বিরতি দেওয়া যায় না ?
rkosegi 26'16

অন্ধকার আমার সংস্করণ @rkosegi, সমস্যা অনুরূপ এই এক । খুব সাধারণ ঘটনা হতে পারে না। এবং যাইহোক, আমি এটি হালকা নোটের (স্পষ্টভাবে একটি খারাপ রসিকতা) বোঝাতে চাইনি। :)
ডিবোস্মিত রে

উত্তর:


119

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

তবে প্রসঙ্গটি হ'ল এটি BufferedInputStreamএমন একটি শ্রেণি যা উপশৃঙ্খলাবদ্ধ হতে পারে এবং এটি একটি বহু-থ্রেড প্রসঙ্গে কাজ করা দরকার।

ক্লু যে inঘোষিত FilterInputStreamহয় protected volatile। তার মানে এমন একটি সম্ভাবনা রয়েছে যা একটি সাবক্লাসে পৌঁছাতে এবং নির্ধারিত nullকরতে পারে in। সেই সম্ভাবনাটি দেওয়া, একটি জাতি শর্ত রোধ করার জন্য "উরফ" আসলে সেখানে রয়েছে।

"ওরফে" ছাড়াই কোডটি বিবেচনা করুন

private InputStream getInIfOpen() throws IOException {
    if (in == null)
        throw new IOException("Stream closed");
    return in;
}
  1. থ্রেড এ কল getInIfOpen()
  2. থ্রেড এ মূল্যায়ন করে in == nullদেখেছে যে inতা নয় null
  3. থ্রেড বি নিয়োগ nullকরে in
  4. থ্রেড এ কার্যকর করে return in। যা ফিরে আসে nullকারণa একটি volatile

"উরফ" এটি প্রতিরোধ করে। এখন inকেবল একবার থ্রেড এ দ্বারা পড়া হয় থ্রেড বি যদি থ্রেড এ এর nullপরে অ্যাসাইন করে তবে তাতে inকিছু আসে যায় না। থ্রেড এ হয় একটি ব্যতিক্রম নিক্ষেপ করবে বা একটি (গ্যারান্টিযুক্ত) নন-নাল মান প্রদান করবে।


11
যা দেখায় যে কেন protectedবহিষ্কারগুলি বহু-থ্রেড প্রসঙ্গে।
মিক মনিমনিক

2
এটা সত্যিই না। যাইহোক, আফাইক এই ক্লাসগুলি জাভা 1.0 এ ফিরে যায়। এটি একটি দুর্বল ডিজাইনের সিদ্ধান্তের অন্য একটি উদাহরণ যা গ্রাহক কোড ভঙ্গ করার ভয়ে স্থির করা যায়নি।
স্টিফেন সি

2
@ স্টেফেনসি বিস্তারিত ব্যাখ্যা +1 করার জন্য ধন্যবাদ। সুতরাং এর অর্থ কি, protectedআমাদের কোডটিতে ভেরিয়েবলগুলি ব্যবহার করা উচিত নয় যদি এটি বহু-থ্রেডযুক্ত হয়?
মধুসূদন রেড্ডি সুন্নাপু

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

3
@ সাম - ১) এটির জন্য সমস্ত বর্ণের অবস্থা এবং রাজ্যগুলি ব্যাখ্যা করার দরকার নেই। উত্তরের উদ্দেশ্য হ'ল এই আপাতদৃষ্টিতে অবর্ণনীয় কোডটি বাস্তবে কেন প্রয়োজনীয়। 2) কিভাবে?
স্টিফেন সি

20

এটি ক্লাস কারণ BufferedInputStream বহু-থ্রেডযুক্ত ব্যবহারের জন্য ডিজাইন করা হয়েছে।

এখানে, আপনি ঘোষণাটি দেখুন in, যা অভিভাবক শ্রেণিতে স্থাপন করা হয়েছে FilterInputStream:

protected volatile InputStream in;

যেহেতু এটি হ'ল protected, এর মান FilterInputStreamসহ BufferedInputStreamএবং এর উপশ্রেণীর যে কোনও উপশ্রেণীর দ্বারা পরিবর্তন করা যেতে পারে । এছাড়াও, এটি ঘোষিত হয়েছে volatile, যার অর্থ কোনও থ্রেড যদি ভেরিয়েবলের মান পরিবর্তন করে তবে এই পরিবর্তনটি অন্য সমস্ত থ্রেডে তত্ক্ষণাত প্রতিফলিত হবে। এই সংমিশ্রণটি খারাপ, যেহেতু এর অর্থ ক্লাসটির BufferedInputStreamনিয়ন্ত্রণ বা কখন inপরিবর্তন করা হবে তা জানার কোনও উপায় নেই । সুতরাং, শূন্যতার জন্য চেক এবং রিটার্ন স্টেটমেন্টের মধ্যে মানটিও পরিবর্তন করা যেতে পারে BufferedInputStream::getInIfOpen, যা চেকটিকে কার্যকরভাবে অকেজো করে তোলে। inস্থানীয় ভেরিয়েবলে এটি ক্যাশে করার জন্য একবারের মানটি পড়ে input, পদ্ধতিটি BufferedInputStream::getInIfOpenঅন্যান্য থ্রেডের পরিবর্তনের বিরুদ্ধে সুরক্ষিত, যেহেতু স্থানীয় ভেরিয়েবলগুলি সর্বদা একক থ্রেডের মালিকানাধীন।

এর মধ্যে একটি উদাহরণ রয়েছে BufferedInputStream::close, যা inবাতিল হয়ে যায়:

public void close() throws IOException {
    byte[] buffer;
    while ( (buffer = buf) != null) {
        if (bufUpdater.compareAndSet(this, buffer, null)) {
            InputStream input = in;
            in = null;
            if (input != null)
                input.close();
            return;
        }
        // Else retry in case a new buf was CASed in fill()
    }
}

তাহলে BufferedInputStream::closeঅন্য থ্রেড দ্বারা বলা হয় যখন BufferedInputStream::getInIfOpenমৃত্যুদন্ড কার্যকর করা হবে, এই race অবস্থা উপরে বর্ণিত স্থাপিত হবে।


আমি একমত, যেমন যেহেতু আমরা ভালো জিনিস দেখছি compareAndSet(), CASকোডে এবং মন্তব্য, ইত্যাদি। আমি কোডটিও অনুসন্ধান করেছি এবং BufferedInputStreamঅসংখ্য synchronizedপদ্ধতিও পেয়েছি । সুতরাং, এটি বহু-থ্রেডযুক্ত ব্যবহারের উদ্দেশ্যে করা হয়েছে, যদিও আমি নিশ্চিত যে এটি কখনও সেভাবে ব্যবহার করে নি। যাইহোক, আমি মনে করি আপনার উত্তরটি সঠিক!
স্পার্ক_স্প্রেড

এটি সম্ভবত বোধগম্য কারণ কারণ getInIfOpen()শুধুমাত্র public synchronizedপদ্ধতি থেকে বলা হয় BufferedInputStream
মিক মনিমনিক

6

এটি এমন একটি সংক্ষিপ্ত কোড, তবে, তাত্ত্বিকভাবে, বহু-থ্রেডযুক্ত পরিবেশে, inতুলনা করার পরে ডান পরিবর্তিত হতে পারে, যাতে পদ্ধতিটি যা পরীক্ষা করে না এমন কিছু ফিরিয়ে দিতে পারে (এটি ফিরে আসতে পারে null, এভাবে সঠিকভাবে যা বোঝানো হয়েছিল তা করে প্রতিরোধ).


আমি কি সঠিক যদি আমি বলি যে আপনি পদ্ধতিটি কল করার সময় এবং মূল্য ফেরানোর (বহু-থ্রেডযুক্ত পরিবেশে) সময়ের মধ্যে রেফারেন্স বদলে in যেতে পারে ?
দেবোস্মিত রায় ২

হ্যাঁ, আপনি এটি বলতে পারেন। শেষ পর্যন্ত সম্ভাবনাটি সত্যিই কংক্রিটের মামলার উপর নির্ভর করবে (একটি বাস্তবতার জন্য আমরা জানি যে এটি যে inকোনও সময় পরিবর্তন করতে পারে)।
acdcjunior

4

আমি বিশ্বাস করি inযে স্থানীয় ভেরিয়েবলের ক্লাস ভেরিয়েবল ক্যাপচারিং হ'ল চলমান অবস্থায় অন্য থ্রেড দ্বারা পরিবর্তন করা inputহলে বেমানান আচরণ রোধ করা ।ingetInIfOpen()

লক্ষ্য করুন যে এর মালিক inপিতামাতা শ্রেণি এবং এটি হিসাবে চিহ্নিত করে না final

এই প্যাটার্নটি ক্লাসের অন্যান্য অংশে প্রতিলিপিযুক্ত এবং যুক্তিসঙ্গত প্রতিরক্ষা কোডিং বলে মনে হচ্ছে।

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