Concurrency & Synchronization
যখন একাধিক প্রসেস বা থ্রেড একই সময়ে চলে এবং শেয়ার্ড রিসোর্স (যেমন মেমোরি, ফাইল) এক্সেস করে, তখন বিভিন্ন সমস্যা দেখা দিতে পারে। এই সমস্যাগুলো সমাধানের জন্য Synchronization প্রয়োজন।
1. Race Conditions
Race Condition হয় যখন একাধিক থ্রেড একই ডেটা একসাথে মডিফাই করার চেষ্টা করে এবং ফলাফল নির্ভর করে কোন থ্রেড কখন রান হলো তার উপর।
Real-life Example: ধরুন একটি ব্যাংক অ্যাকাউন্টে ১০০০ টাকা আছে। দুইজন ব্যক্তি একই সময়ে দুই ATM থেকে ৫০০ টাকা করে তুলতে চাইলো।
- Thread A: Balance পড়লো (১০০০), ৫০০ বিয়োগ করলো, লিখলো ৫০০।
- Thread B: Balance পড়লো (১০০০), ৫০০ বিয়োগ করলো, লিখলো ৫০০।
ফলাফল: ১০০০ টাকা তোলা হলো কিন্তু ব্যালেন্স দেখাচ্ছে ৫০০ (হওয়া উচিত ছিল ০)। এটি একটি Race Condition।
2. Critical Section
Critical Section হলো কোডের সেই অংশ যেখানে শেয়ার্ড রিসোর্স এক্সেস করা হয়। এই অংশে একবারে শুধুমাত্র একটি থ্রেড প্রবেশ করতে পারবে।
Requirements:
- Mutual Exclusion: একবারে একটি থ্রেড।
- Progress: যদি কোনো থ্রেড ক্রিটিক্যাল সেকশনে না থাকে, তাহলে অন্যরা ঢুকতে পারবে।
- Bounded Waiting: কোনো থ্রেড অনন্তকাল অপেক্ষা করবে না।
3. Locks & Semaphores
Mutex (Mutual Exclusion Lock)
একটি লক যা শুধুমাত্র দুইটি স্টেট রাখে: Locked বা Unlocked। যে থ্রেড লক করেছে, শুধু সেই আনলক করতে পারবে।
lock.acquire() # লক নাও
# Critical Section
lock.release() # লক ছেড়ে দাওSemaphore
একটি কাউন্টার যা নির্দিষ্ট সংখ্যক থ্রেডকে একসাথে রিসোর্স এক্সেস করতে দেয়।
- Binary Semaphore: ০ বা ১ (Mutex-এর মতো)।
- Counting Semaphore: যেকোনো পজিটিভ সংখ্যা (যেমন ৫টি প্রিন্টার আছে, তাহলে ৫টি থ্রেড একসাথে প্রিন্ট করতে পারবে)।
4. Deadlocks
Deadlock হয় যখন দুই বা ততোধিক প্রসেস একে অপরের জন্য অপেক্ষা করে এবং কেউই এগোতে পারে না।
Real-life Example: দুইটি গাড়ি সরু রাস্তার দুই প্রান্ত থেকে আসছে। কেউই পিছাতে চায় না। উভয়ে আটকে গেলো।
Deadlock-এর চারটি শর্ত (সবগুলো একসাথে থাকতে হবে):
- Mutual Exclusion: রিসোর্স একবারে একজন ব্যবহার করতে পারবে।
- Hold and Wait: একটি রিসোর্স ধরে রেখে অন্যটির জন্য অপেক্ষা করছে।
- No Preemption: জোর করে রিসোর্স কেড়ে নেওয়া যায় না।
- Circular Wait: P1 → P2 → P3 → P1 (চক্রাকার নির্ভরতা)।
Deadlock Handling:
- Prevention: উপরের চারটি শর্তের যেকোনো একটি ভাঙা।
- Avoidance: Banker's Algorithm ব্যবহার করে সেফ স্টেট নিশ্চিত করা।
- Detection & Recovery: Deadlock হয়ে গেলে ডিটেক্ট করা এবং একটি প্রসেস কিল করা।
5. Monitors & Condition Variables
Monitor হলো একটি হাই-লেভেল সিনক্রোনাইজেশন কনস্ট্রাক্ট যা অটোমেটিক লকিং প্রদান করে। প্রোগ্রামারকে ম্যানুয়ালি lock() এবং unlock() কল করতে হয় না।
Condition Variables ব্যবহার করা হয় থ্রেডকে নির্দিষ্ট কন্ডিশনের জন্য অপেক্ষা করাতে।
- wait(): থ্রেড ঘুমিয়ে পড়ে।
- signal(): একটি ঘুমন্ত থ্রেডকে জাগায়।
- broadcast(): সব ঘুমন্ত থ্রেডকে জাগায়।
Example Use Case: Producer-Consumer Problem সমাধানে Monitor ব্যবহার করা হয়।