আমি জন এর মন্তব্যের সাথে একমত: আপনার ভেরিয়েবলের রেফারেন্স পরিবর্তনের ক্ষেত্রে অসামঞ্জস্যতা রোধ করতে একটি চূড়ান্ত লক ডামি ব্যবহার করার সময় আপনাকে সর্বদা চূড়ান্ত লক ডামি ব্যবহার করতে হবে । সুতরাং যে কোনও ক্ষেত্রে এবং থাম্বের প্রথম নিয়ম হিসাবে:
নিয়ম # 1: ক্ষেত্রটি চূড়ান্ত না হলে সর্বদা একটি (ব্যক্তিগত) চূড়ান্ত লক ডামি ব্যবহার করুন।
কারণ # 1: আপনি লকটি ধরে রেখে ভেরিয়েবলের রেফারেন্সটি নিজেই পরিবর্তন করেন। সিঙ্ক্রোনাইজড লকের বাইরে অপেক্ষা করা অন্য একটি থ্রেড সুরক্ষিত ব্লকে প্রবেশ করতে সক্ষম হবে।
কারণ # 2: আপনি লকটি ধরে রেখেছেন এবং অন্য একটি থ্রেড ভেরিয়েবলের রেফারেন্স পরিবর্তন করে। ফলাফল একই: অন্য থ্রেড রক্ষিত ব্লকে প্রবেশ করতে পারে।
তবে চূড়ান্ত লক ডামি ব্যবহার করার সময়, আরও একটি সমস্যা রয়েছে : আপনি ভুল ডেটা পেতে পারেন, কারণ আপনার অ-চূড়ান্ত অবজেক্টটি কেবল সিঙ্ক্রোনাইজ (অবজেক্ট) কল করার সময় র্যামের সাথে সিঙ্ক্রোনাইজ হবে। সুতরাং, থাম্বের দ্বিতীয় নিয়ম হিসাবে:
বিধি # 2: একটি চূড়ান্ত নয় এমন অবজেক্টটি লক করার সময় আপনাকে উভয়ই করতে হবে: র্যাম সিঙ্ক্রোনাইজেশনের জন্য চূড়ান্ত লক ডামি এবং চূড়ান্ত অবজেক্টের লকটি ব্যবহার করা। (একমাত্র বিকল্প হ'ল বস্তুর সমস্ত ক্ষেত্রকে অস্থির হিসাবে ঘোষণা করা হবে!)
এই লকগুলি "নেস্টেড লকস" নামেও পরিচিত। নোট করুন যে আপনাকে অবশ্যই সর্বদা একই ক্রমে কল করতে হবে, অন্যথায় আপনি একটি মৃত লক পাবেন :
public class X {
private final LOCK;
private Object o;
public void setO(Object o){
this.o = o;
}
public void x() {
synchronized (LOCK) {
synchronized(o){
}
}
}
}
আপনি দেখতে পাচ্ছেন যে আমি দুটি লকটি সরাসরি একই লাইনে লিখি কারণ তারা সর্বদা এক সাথে থাকে। এটির মতো, আপনি এমনকি 10 টি নেস্টিং লকও করতে পারেন:
synchronized (LOCK1) {
synchronized (LOCK2) {
synchronized (LOCK3) {
synchronized (LOCK4) {
}
}
}
}
মনে রাখবেন যে আপনি যদি synchronized (LOCK3)
অন্য থ্রেডের মতো কেবল একটি অভ্যন্তরীণ লক অর্জন করেন তবে এই কোডটি ভাঙবে না । আপনি যদি অন্য থ্রেডে এরকম কিছু কল করেন তবে এটি ভেঙে যাবে:
synchronized (LOCK4) {
synchronized (LOCK1) {
synchronized (LOCK3) {
synchronized (LOCK2) {
}
}
}
}
চূড়ান্ত নয় এমন ক্ষেত্রগুলি পরিচালনা করার সময় যেমন নেস্টেড লকগুলির চারপাশে কেবলমাত্র একটি কাজ রয়েছে:
বিধি # 2 - বিকল্প: বস্তুর সমস্ত ক্ষেত্রকে অস্থির হিসাবে ঘোষণা করুন। (আমি এখানে এটি করার অসুবিধাগুলি সম্পর্কে কথা বলব না, উদাহরণস্বরূপ পাঠের ক্ষেত্রেও এক্স-লেভেল ক্যাশে থাকা কোনও স্টোরেজ প্রতিরোধ করা))
সুতরাং আইওউবটি বেশ সঠিক: কেবল java.util.concurrent ব্যবহার করুন। অথবা সিঙ্ক্রোনাইজেশন সম্পর্কে সমস্ত কিছু বুঝতে শুরু করুন এবং নেস্টেড লকগুলি দিয়ে নিজেই এটি করুন। ;)
চূড়ান্ত নয় এমন ক্ষেত্রগুলিতে কেন সিঙ্ক্রোনাইজেশন বিরতি দেয় সে সম্পর্কে আরও তথ্যের জন্য আমার পরীক্ষার কেসটি দেখুন: https://stackoverflow.com/a/21460055/2012947
এবং র্যাম এবং ক্যাশেগুলির কারণে আপনাকে কেন একেবারে সিঙ্ক্রোনাইজ করা দরকার তা আরও বিশদের জন্য এখানে দেখুন: https://stackoverflow.com/a/21409975/2012947
o
সিঙ্ক্রোনাইজড ব্লকটি পৌঁছানোর সময় উল্লেখ করা অবজেক্টটির একচেটিয়া অ্যাক্সেস নিয়ে চলে runs যদি অবজেক্টটিo
পরিবর্তনগুলি বোঝায়, অন্য থ্রেড বরাবর এসে সিঙ্ক্রোনাইজড কোড ব্লক কার্যকর করতে পারে।