মাল্টিথ্রেডেড প্রোগ্রামিংয়ে Livelock এবং Starvation দুটি সাধারণ সমস্যা, যা থ্রেড পারফরম্যান্স এবং কার্যকারিতায় বাধা সৃষ্টি করতে পারে। এগুলোর মূল কারণ হল থ্রেডগুলির অপ্রয়োজনীয় অপেক্ষা বা অসম সম্পদের বণ্টন। নিচে এগুলোর ধারণা, উদাহরণ এবং সমাধান ব্যাখ্যা করা হয়েছে।
Livelock
ধারণা
- Livelock তখন ঘটে যখন দুটি বা তার বেশি থ্রেড একে অপরের সাথে সহযোগিতা করার চেষ্টা করে, কিন্তু একটি নির্দিষ্ট শর্ত পূরণ করতে ব্যর্থ হয়। ফলে তারা কার্যত অকার্যকর অবস্থায় আটকে যায়, কিন্তু থ্রেডগুলো স্থির না থেকে ক্রমাগত চলতে থাকে।
- এটি Deadlock থেকে আলাদা কারণ Livelock-এ থ্রেডগুলো স্থবির নয়, বরং কাজ করছে কিন্তু কোনো ফলাফল দিতে পারছে না।
উদাহরণ: Livelock
class Resource {
private boolean isAvailable = true;
public synchronized boolean isAvailable() {
return isAvailable;
}
public synchronized void toggleAvailability() {
isAvailable = !isAvailable;
}
}
public class LivelockExample {
public static void main(String[] args) {
Resource resource = new Resource();
Thread thread1 = new Thread(() -> {
while (resource.isAvailable()) {
System.out.println("Thread 1: Waiting for resource to become unavailable.");
resource.toggleAvailability();
try {
Thread.sleep(100); // অন্য থ্রেডকে সময় দেয়
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
while (!resource.isAvailable()) {
System.out.println("Thread 2: Waiting for resource to become available.");
resource.toggleAvailability();
try {
Thread.sleep(100); // অন্য থ্রেডকে সময় দেয়
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
}
}
সমাধান:
- ব্যাক-অফ স্ট্র্যাটেজি ব্যবহার করুন: থ্রেডগুলোকে তাদের কার্যকলাপ ধীর করতে বা সম্পদ ছেড়ে দিতে বাধ্য করুন।
- টাইমআউট ব্যবহার করুন: থ্রেডগুলোকে একটি নির্দিষ্ট সময় পরে থেমে যেতে বাধ্য করুন।
- অ্যালগরিদম পুনর্বিবেচনা করুন: এমন অ্যালগরিদম তৈরি করুন যা সহ-সমন্বয়ের সময় আটকে না যায়।
Starvation
ধারণা
- Starvation তখন ঘটে যখন একটি থ্রেড সম্পদের অভাবে (যেমন লক বা প্রসেসর টাইম) অনির্দিষ্টকাল ধরে কাজ করতে পারে না।
- এটি তখন হয় যখন উচ্চ অগ্রাধিকারযুক্ত থ্রেড বারবার কম অগ্রাধিকারযুক্ত থ্রেডকে বাধা দেয়।
উদাহরণ: Starvation
import java.util.concurrent.locks.ReentrantLock;
public class StarvationExample {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Runnable lowPriorityTask = () -> {
while (true) {
if (lock.tryLock()) {
try {
System.out.println("Low-priority task running...");
Thread.sleep(50); // কাজ সম্পন্ন করছে
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
};
Runnable highPriorityTask = () -> {
while (true) {
lock.lock(); // সরাসরি লক নিয়ে নিচ্ছে
try {
System.out.println("High-priority task running...");
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
Thread lowPriority = new Thread(lowPriorityTask);
Thread highPriority = new Thread(highPriorityTask);
lowPriority.setPriority(Thread.MIN_PRIORITY);
highPriority.setPriority(Thread.MAX_PRIORITY);
lowPriority.start();
highPriority.start();
}
}
সমাধান:
- Fair Lock ব্যবহার করুন:
ReentrantLockএর fairness policy ব্যবহার করে।উদাহরণ:
ReentrantLock lock = new ReentrantLock(true); // Fair lock
- অগ্রাধিকার পুনর্বিন্যাস করুন:
- থ্রেডগুলোর অগ্রাধিকার মান পুনঃবিন্যাস করুন যাতে কম অগ্রাধিকারযুক্ত থ্রেডও সম্পদ পায়।
- রিসোর্স শেয়ারিং পলিসি পরিবর্তন করুন:
- সম্পদ ব্যবহারের একটি সুষম পদ্ধতি প্রয়োগ করুন।
উভয়ের তুলনা
| প্যারামিটার | Livelock | Starvation |
|---|---|---|
| করণীয় অবস্থা | থ্রেডগুলি সক্রিয় থাকে কিন্তু কোনো কাজ সম্পন্ন করতে পারে না। | থ্রেডটি সম্পদ পায় না এবং কাজ সম্পন্ন করতে পারে না। |
| মূল কারণ | থ্রেডগুলির অতিরিক্ত সহযোগিতা। | কম অগ্রাধিকার থ্রেড অবহেলিত। |
| সমাধান কৌশল | ব্যাক-অফ স্ট্র্যাটেজি, টাইমআউট। | ফেয়ার লক, অগ্রাধিকার পুনর্বিন্যাস। |
একটি বাস্তব উদাহরণ: Livelock এবং Starvation সমাধান
নিচের উদাহরণে ReentrantLock ব্যবহার করে Starvation এড়ানো হয়েছে এবং tryLock() এর মাধ্যমে Livelock সমাধান করা হয়েছে:
import java.util.concurrent.locks.ReentrantLock;
public class CombinedSolution {
private static final ReentrantLock lock = new ReentrantLock(true); // Fair lock
public static void main(String[] args) {
Runnable task = () -> {
while (true) {
try {
if (lock.tryLock()) { // Livelock এড়াতে tryLock
try {
System.out.println(Thread.currentThread().getName() + " is running.");
Thread.sleep(100); // কাজ করছে
} finally {
lock.unlock();
}
break; // কাজ শেষ হলে লুপ থেকে বেরিয়ে আসা
} else {
System.out.println(Thread.currentThread().getName() + " is waiting.");
Thread.sleep(50); // ব্যাক-অফ স্ট্র্যাটেজি
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(task, "Thread-1");
Thread thread2 = new Thread(task, "Thread-2");
thread1.start();
thread2.start();
}
}
- Livelock: থ্রেডগুলো অকার্যকর লুপে আটকে থাকে। সমাধান:
- টাইমআউট এবং ব্যাক-অফ স্ট্র্যাটেজি।
- Starvation: কম অগ্রাধিকার থ্রেড সম্পদ পায় না। সমাধান:
- ফেয়ার লক এবং অগ্রাধিকার সমন্বয়।
এই সমস্যাগুলো সমাধান করলে মাল্টিথ্রেডেড অ্যাপ্লিকেশন আরো কার্যকর ও নির্ভরযোগ্য হবে।
Content added By
Read more