অ্যাটমিকবুলিয়ান এমন কী করে যা একটি উদ্বায়ী বুলেটিয়ান অর্জন করতে পারে না?
অ্যাটমিকবুলিয়ান এমন কী করে যা একটি উদ্বায়ী বুলেটিয়ান অর্জন করতে পারে না?
উত্তর:
এরা একেবারেই আলাদা। একটি volatile
পূর্ণসংখ্যার উদাহরণটি বিবেচনা করুন :
volatile int i = 0;
void incIBy5() {
i += 5;
}
দুটি থ্রেড যদি একই সাথে ফাংশনটি কল করে তবে i
এটি 5 পরে হতে পারে, যেহেতু সংকলিত কোডটি এর সাথে কিছুটা অনুরূপ হবে (আপনি যদি সিঙ্ক্রোনাইজ করতে না পারেন তবে int
):
void incIBy5() {
int temp;
synchronized(i) { temp = i }
synchronized(i) { i = temp + 5 }
}
যদি কোনও পরিবর্তনশীল অস্থির হয় তবে এর প্রতিটি পারমাণবিক অ্যাক্সেস সিঙ্ক্রোনাইজ করা হয় তবে বাস্তবে এটি কী পারমাণবিক অ্যাক্সেস হিসাবে যোগ্যতা অর্জন করে তা সর্বদা স্পষ্ট নয়। একটি Atomic*
বস্তুর সাথে, এটি গ্যারান্টিযুক্ত যে প্রতিটি পদ্ধতি "পরমাণু"।
সুতরাং, আপনি যদি একটি AtomicInteger
এবং ব্যবহার করেন getAndAdd(int delta)
, আপনি নিশ্চিত হতে পারেন যে ফলাফলটি হবে 10
। একইভাবে, যদি দুটি থ্রেড উভয়ই boolean
একই সাথে একটি চলককে অস্বীকার করে , একটি দিয়ে AtomicBoolean
আপনি নিশ্চিত হতে পারেন যে এটির পরে এর মূল মূল্য আছে তবে volatile boolean
আপনি এটি করতে পারবেন না।
সুতরাং যখনই আপনার একটি ক্ষেত্রকে সংশোধন করার একাধিক থ্রেড রয়েছে , আপনার এটিকে অণু তৈরি করতে হবে বা সুস্পষ্ট সিঙ্ক্রোনাইজেশন ব্যবহার করতে হবে।
উদ্দেশ্য volatile
একটি ভিন্ন এক। এই উদাহরণ বিবেচনা করুন
volatile boolean stop = false;
void loop() {
while (!stop) { ... }
}
void stop() { stop = true; }
আপনার যদি থ্রেড চলমান loop()
এবং অন্য থ্রেড কলিং stop()
থাকে তবে আপনি বাদ দিলে আপনি একটি অসীম লুপের মধ্যে চলে যেতে পারেন volatile
, যেহেতু প্রথম থ্রেড স্টপের মানকে ক্যাশে করতে পারে। এখানে, volatile
অপ্টিমাইজেশানগুলির সাথে কিছুটা সতর্ক হতে সংকলকটির জন্য ইঙ্গিত হিসাবে কাজ করে।
volatile
। প্রশ্ন volatile boolean
বনাম সম্পর্কে AtomicBoolean
।
volatile boolean
তা যথেষ্ট। যদি অনেক লেখক থাকে তবে আপনার প্রয়োজন হতে পারে AtomicBoolean
।
আমি যখন অস্থির ক্ষেত্রগুলি বলি যখন ক্ষেত্রটি কেবল তার মালিকের থ্রেড দ্বারা আপডেট হয় এবং মানটি কেবল অন্য থ্রেড দ্বারা পঠিত হয় তবে আপনি এটিকে একটি প্রকাশ / সাবস্ক্রাইব দৃশ্যে ভাবতে পারেন যেখানে অনেক পর্যবেক্ষক রয়েছে তবে কেবলমাত্র একজন প্রকাশক রয়েছে। তবে যদি সেই পর্যবেক্ষকরা অবশ্যই ক্ষেত্রের মানের ভিত্তিতে কিছু যুক্তি সম্পাদন করতে পারেন এবং তারপরে একটি নতুন মান পিছনে ঠেকান তবে আমি পরমাণু * ওয়ার্স বা লকগুলি বা সিঙ্ক্রোনাইজড ব্লকগুলিতে যাই যা আমার পক্ষে সবচেয়ে উপযুক্ত। অনেক সমসাময়িক পরিস্থিতিতে এটি মান পেতে উত্সাহিত হয়, এটি অন্যটির সাথে তুলনা করুন এবং প্রয়োজনে আপডেট করুন, সুতরাং অ্যাটমিক * শ্রেণিতে উপস্থিত তুলনাআন্ডসেট এবং গেটএন্ডসেট পদ্ধতিগুলি।
পারমাণবিক ক্লাসগুলির একটি তালিকা এবং তারা কীভাবে কাজ করে তার একটি দুর্দান্ত ব্যাখ্যাের জন্য java.util.concurrent.atomic প্যাকেজের জাভাডোকগুলি পরীক্ষা করুন (কেবল শিখেছেন যে তারা লক-মুক্ত রয়েছে, তাই তাদের তালা বা সংক্রামযুক্ত ব্লকের উপর একটি সুবিধা রয়েছে)
boolean
আমাদের বেছে নেওয়া উচিত volatile boolean
।
আপনি ব্যবহার করতে পারবেন না compareAndSet
, getAndSet
উদ্বায়ী বুলিয়ান সঙ্গে পারমাণবিক অপারেশন হিসাবে (অবশ্যই, যদি না আপনি এটা সুসংগত)।
AtomicBoolean
এমন পদ্ধতি রয়েছে যা তাদের যৌগিক ক্রিয়াকলাপগুলি পরমাণুভাবে এবং কোনও synchronized
ব্লক ব্যবহার না করেই সম্পাদন করে । অন্যদিকে, volatile boolean
যদি কোনও synchronized
ব্লকের মধ্যে এমনটি করা হয় তবে কেবল যৌগিক ক্রিয়াকলাপ সম্পাদন করতে পারে ।
পড়ার / লেখার স্মৃতি প্রভাবগুলি যথাক্রমে এবং পদ্ধতিগুলির সাথে volatile boolean
অভিন্ন ।get
set
AtomicBoolean
উদাহরণস্বরূপ compareAndSet
পদ্ধতিটি পরমাণুভাবে নিম্নলিখিতগুলি সম্পাদন করবে (একটি synchronized
ব্লক ছাড়াই ):
if (value == expectedValue) {
value = newValue;
return true;
} else {
return false;
}
অতএব, compareAndSet
পদ্ধতিটি আপনাকে এমন একাধিক থ্রেড থেকে কল করা হলেও কোডটি লিখতে দেবে যা কেবল একবার কার্যকর করার গ্যারান্টিযুক্ত। উদাহরণ স্বরূপ:
final AtomicBoolean isJobDone = new AtomicBoolean(false);
...
if (isJobDone.compareAndSet(false, true)) {
listener.notifyJobDone();
}
নিশ্চিত করা হয় শুধুমাত্র এক বার (অন্য কোন থ্রেড সেট অভিমানী শ্রোতা অবহিত AtomicBoolean
ফিরে false
এটি সেট হওয়ার পর আবার true
)।
volatile
মূলশব্দটি গ্যারান্টি দেয় যে থ্রেডগুলি ভাগ করে নেওয়ার আগে সম্পর্কের আগে সেই পরিবর্তনশীল। এটি আপনাকে গ্যারান্টি দেয় না যে 2 বা ততোধিক থ্রেডগুলি সেই বুলিয়ান ভেরিয়েবলটি অ্যাক্সেস করার সময় একে অপরকে বাধা দেয় না।
Atomic*
শ্রেণি একটি volatile
ক্ষেত্র জড়ায় ।
উদ্বায়ী বুলেটিয়ান বনাম অ্যাটমিকবুলিয়ান
পারমাণবিক * ক্লাসগুলি একই ধরণের একটি উদ্বায়ী আদিমকে আবদ্ধ করে। উত্স থেকে:
public class AtomicLong extends Number implements java.io.Serializable {
...
private volatile long value;
...
public final long get() {
return value;
}
...
public final void set(long newValue) {
value = newValue;
}
সুতরাং আপনি যদি যা করছেন তার সবই যদি পারমাণবিক * পেতে এবং সেট করা হয় তবে আপনার পরিবর্তে কেবল একটি অস্থির ক্ষেত্র থাকতে পারে।
অ্যাটমিকবুলিয়ান এমন কী করে যা একটি উদ্বায়ী বুলেটিয়ান অর্জন করতে পারে না?
আণবিক * শ্রেণীর আপনি পদ্ধতি যেমন আরো উন্নত কার্যকারিতা প্রদান দিতে incrementAndGet()
, compareAndSet()
, এবং অন্যদের যে লকিং ছাড়া একাধিক কার্যকলাপ (পেতে / বৃদ্ধি / সেট, পরীক্ষা / সেট থাকে) বাস্তবায়ন। এ কারণেই পারমাণবিক * শ্রেণিগুলি এত শক্তিশালী।
উদাহরণস্বরূপ, যদি একাধিক থ্রেড নিম্নলিখিত কোডগুলি ব্যবহার করে ব্যবহার করে তবে ++
রেসের শর্ত থাকবে কারণ ++
বাস্তবে: পান, বৃদ্ধি এবং সেট করুন।
private volatile value;
...
// race conditions here
value++;
তবে, নিম্নলিখিত কোডটি লক ছাড়াই নিরাপদে বহু-থ্রেড পরিবেশে কাজ করবে:
private final AtomicLong value = new AtomicLong();
...
value.incrementAndGet();
এটাও লক্ষ করা জরুরী যে পারমাণবিক * বর্গ ব্যবহার করে আপনার উদ্বায়ী ক্ষেত্রটি মুড়িয়ে ফেলা একটি অবজেক্টের দৃষ্টিকোণ থেকে সমালোচনামূলকভাবে ভাগ করা সংস্থানকে আবদ্ধ করার একটি ভাল উপায়। এর অর্থ হল যে বিকাশকারীরা ক্ষেত্রটি ++ এর সাথে সম্ভবত ইনজেকশনের সমস্যাগুলি সম্ভবত ভাগ করে নেওয়া হচ্ছে তা ধরে নিয়ে ক্ষেত্রটি মোকাবেলা করতে পারবেন না; বা অন্যান্য কোড যা জাতি শর্ত প্রবর্তন করে।
যদি শ্রেণি স্তরের ভেরিয়েবল অ্যাক্সেস করে একাধিক থ্রেড থাকে তবে প্রতিটি থ্রেড সেই পরিবর্তনশীলটির অনুলিপিটি তার থ্রডলোকাল ক্যাশে রাখতে পারে।
ভেরিয়েবলটিকে অস্থির করে তুলতে থ্রেডলোকাল ক্যাশে ভেরিয়েবলের অনুলিপি রাখা থ্রেডগুলিকে আটকাবে।
পারমাণবিক পরিবর্তনশীলগুলি পৃথক এবং তারা তাদের মানগুলিতে পারমাণবিক পরিবর্তনের অনুমতি দেয়।
বুলিয়ান আদিম প্রকারটি লেখার এবং পড়ার ক্রিয়াকলাপগুলির জন্য পারমাণবিক, অস্থায়ী হওয়ার আগে-নীতিটির গ্যারান্টি দেয়। সুতরাং আপনার যদি সহজ সরল () এবং সেট () সেট করতে হয় তবে আপনার অ্যাটমিকবুলিয়ান লাগবে না।
অন্যদিকে, আপনার যদি কোনও ভেরিয়েবলের মান নির্ধারণের আগে কিছু পরীক্ষা করার প্রয়োজন হয়, যেমন "যদি সত্য হয় তবে মিথ্যাতে সেট হয়ে থাকে", তবে আপনাকে পরমাণুভাবেও এই অপারেশনটি করতে হবে, এক্ষেত্রে তুলনাঅ্যান্ডসেট এবং প্রদত্ত অন্যান্য পদ্ধতিগুলি ব্যবহার করুন অ্যাটমিকবুলিয়ান, যেহেতু আপনি যদি এই যুক্তিটিকে অস্থির বুলিয়ানের সাথে বাস্তবায়িত করার চেষ্টা করেন তবে আপনাকে কিছুটা সিঙ্ক্রোনাইজেশন করতে হবে তা নিশ্চিত হওয়ার জন্য যে মানটি গেট এবং সেট এর মধ্যে পরিবর্তিত হয়নি।
IDIOM মনে রাখবেন -
পড়ুন - মোডিফাই করুন - এইটি লিখুন আপনি অস্থিরতার সাথে অর্জন করতে পারবেন না
volatile
কেবলমাত্র সেই ক্ষেত্রে কাজ করে যেখানে মালিকের থ্রেডের ক্ষেত্রে ক্ষেত্রের মান আপডেট করার ক্ষমতা থাকে এবং অন্যান্য থ্রেডগুলি কেবলমাত্র পড়তে পারে।
আপনার বুলিয়ান পরিবর্তন করতে যদি আপনার কাছে কেবল একটি থ্রেড থাকে তবে আপনি একটি অস্থির বুলেটিয়ান ব্যবহার করতে পারেন (সাধারণত আপনি stop
থ্রেডের মূল লুপটিতে পরীক্ষা করা একটি ভেরিয়েবল সংজ্ঞায়িত করতে এটি করেন)।
তবে, আপনার যদি বুলিয়ান পরিবর্তন করে একাধিক থ্রেড থাকে, আপনার একটি ব্যবহার করা উচিত AtomicBoolean
। অন্যথায়, নিম্নলিখিত কোডটি নিরাপদ নয়:
boolean r = !myVolatileBoolean;
এই অপারেশনটি দুটি পদক্ষেপে করা হয়:
একটি অন্য থ্রেডের মধ্যে মান পরিবর্তন যদি #1
এবং 2#
, আপনি একটি ভুল ফলাফল পেয়েছি পারে। AtomicBoolean
পদ্ধতিগুলি পদক্ষেপ #1
এবং #2
পারমাণবিকভাবে এই সমস্যাটি এড়ায়।
উভয়ই একই ধারণার তবে পারমাণবিক বুলিয়ান এটি সিপিইউ সুইচ এর মধ্যে ঘটতে পারলে এটি অপারেশনে পারমাণবিকতা সরবরাহ করবে।