Race Condition: কী?
Race Condition এমন একটি অবস্থা, যখন একাধিক থ্রেড একই রিসোর্স বা ডেটাতে একসাথে অ্যাক্সেস করতে চেষ্টা করে এবং ডেটা সংক্রান্ত সমস্যা সৃষ্টি হয়। এটি ঘটে যদি:
- একাধিক থ্রেড একই ডেটা বা মেমোরি পরিবর্তন করে।
- ডেটা অ্যাক্সেস করার সিকোয়েন্স প্রেডিক্টেবল না হয়।
Race Condition এর উদাহরণ:
class Counter {
private int count = 0;
public void increment() {
count++; // এই লাইনটি Race Condition এর শিকার হতে পারে
}
public int getCount() {
return count;
}
}
public class RaceConditionExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final Count: " + counter.getCount()); // সম্ভাব্য ফলাফল সঠিক নাও হতে পারে
}
}
সমস্যা:
উপরের কোডে, count++ অপারেশন তিনটি ধাপে হয়:
countপড়া।countইনক্রিমেন্ট করা।- নতুন মান স্টোর করা।
যদি দুইটি থ্রেড একই সময়ে এই অপারেশন সম্পাদন করতে চায়, তাহলে Race Condition হতে পারে, এবং count এর মান সঠিক হবে না।
Synchronization: কেন দরকার?
Synchronization ব্যবহৃত হয় Race Condition প্রতিরোধ করতে। এটি নিশ্চিত করে যে এক সময়ে শুধুমাত্র একটি থ্রেড একটি নির্দিষ্ট ব্লকে বা মেথডে প্রবেশ করতে পারবে।
Synchronization এর উদাহরণ:
class Counter {
private int count = 0;
public synchronized void increment() { // সিঙ্ক্রোনাইজড ব্লক
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizedExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final Count: " + counter.getCount()); // ফলাফল সবসময় সঠিক হবে
}
}
কীভাবে কাজ করে?
synchronizedকীওয়ার্ড ব্যবহার করলে, এক সময়ে শুধুমাত্র একটি থ্রেডincrement()মেথডে প্রবেশ করতে পারবে।- এটি একটি monitor lock তৈরি করে, যা থ্রেডকে ক্রমবদ্ধভাবে ডেটা অ্যাক্সেস করতে দেয়।
Alternative: Synchronized Block
সম্পূর্ণ মেথড সিঙ্ক্রোনাইজড না করে নির্দিষ্ট কোড ব্লক সিঙ্ক্রোনাইজড করা যেতে পারে।
class Counter {
private int count = 0;
public void increment() {
synchronized (this) { // শুধুমাত্র এই ব্লকটি সিঙ্ক্রোনাইজড
count++;
}
}
public int getCount() {
return count;
}
}
Java Concurrency Tools ব্যবহার করে Synchronization
১. ReentrantLock: ReentrantLock একটি আরও ফাইন-গ্রেইনড লক মেকানিজম প্রদান করে।
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // সবসময় লক মুক্ত করুন
}
}
public int getCount() {
return count;
}
}
Race Condition এর প্রতিরোধে Synchronization কেন গুরুত্বপূর্ণ?
- ডেটা ইন্টিগ্রিটি: ডেটার সঠিকতা এবং ধারাবাহিকতা বজায় রাখা।
- ডেটা রেস এড়ানো: একাধিক থ্রেডের মধ্যে ডেটা অ্যাক্সেস কন্ট্রোল করা।
- ডেডলক প্রতিরোধ: সঠিকভাবে সিঙ্ক্রোনাইজ না করলে থ্রেড ডেডলক হতে পারে।
Race Condition এবং Synchronization এর চ্যালেঞ্জ
- সঠিকভাবে Synchronization না করলে ডেডলক এবং পারফরম্যান্স সমস্যা হতে পারে।
- অতিরিক্ত Synchronization অ্যাপ্লিকেশনের পারফরম্যান্স হ্রাস করতে পারে।
Race Condition জাভা কনকারেন্সির একটি সাধারণ সমস্যা যা ডেটার সঠিকতা নষ্ট করে। Synchronization এর মাধ্যমে এই সমস্যা সমাধান করা যায়। তবে, প্রতিটি ক্ষেত্রে Synchronization ব্যবহার করার আগে এর প্রভাব এবং চ্যালেঞ্জগুলো বুঝে প্রয়োগ করা উচিত।
Read more