AtomicInteger হল Java এর java.util.concurrent.atomic প্যাকেজের একটি ক্লাস, যা atomic operations সাপোর্ট করে। এটি মাল্টি-থ্রেডেড পরিবেশে integer values পরিচালনা করার জন্য ব্যবহৃত হয়, যেখানে একাধিক থ্রেড একই ডেটার উপর কাজ করছে। AtomicInteger এর মাধ্যমে ডেটা সঠিকতা (consistency) নিশ্চিত করা হয়, এবং এটি thread-safe।
AtomicInteger এর বৈশিষ্ট্য
- Atomicity: প্রতিটি অপারেশন সম্পূর্ণভাবে "atomic", অর্থাৎ এটি বিভক্ত হয় না।
- Thread-Safety: একাধিক থ্রেড একই সময়ে ডেটার উপর কাজ করলেও এটি সঠিকভাবে পরিচালিত হয়।
- Lock-Free Mechanism: লক ব্যবহার না করেই ডেটা হস্তান্তর করা হয়, যা পারফরম্যান্স বাড়ায়।
- Non-blocking Operations: থ্রেডগুলো ব্লক না হয়েও ডেটা আপডেট করতে পারে।
AtomicInteger কেন প্রয়োজন?
১. Race Condition এড়ানো
মাল্টি-থ্রেডেড পরিবেশে একাধিক থ্রেড যখন একটি সাধারণ integer ভেরিয়েবল ব্যবহার করে, তখন Race Condition হতে পারে। AtomicInteger এই সমস্যা প্রতিরোধ করে।
২. Thread-Safe Increment/Decrement
int বা long ডেটা টাইপের ভেরিয়েবল ম্যানিপুলেশনের সময় সিঙ্ক্রোনাইজেশন প্রয়োজন হয়। কিন্তু AtomicInteger এই অপারেশনগুলো synchronized blocks ছাড়াই নিরাপদে সম্পন্ন করতে পারে।
৩. Performance Optimization
AtomicInteger লক-মুক্ত পদ্ধতি ব্যবহার করে কাজ করায় এটি অনেক দ্রুত কাজ সম্পন্ন করতে পারে।
AtomicInteger ক্লাসের সাধারণ মেথডসমূহ
get()
বর্তমান মান রিটার্ন করে।set(int newValue)
নতুন মান সেট করে।getAndSet(int newValue)
পুরোনো মান রিটার্ন করে এবং নতুন মান সেট করে।incrementAndGet()
মান ১ দ্বারা বৃদ্ধি করে এবং নতুন মান রিটার্ন করে।getAndIncrement()
বর্তমান মান রিটার্ন করে এবং পরে ১ দ্বারা বৃদ্ধি করে।decrementAndGet()
মান ১ দ্বারা কমায় এবং নতুন মান রিটার্ন করে।getAndDecrement()
বর্তমান মান রিটার্ন করে এবং পরে ১ দ্বারা কমায়।addAndGet(int delta)
নির্দিষ্ট মান যোগ করে এবং নতুন মান রিটার্ন করে।compareAndSet(int expect, int update)
যদি বর্তমান মান expect এর সমান হয়, তবে এটি update দ্বারা প্রতিস্থাপিত হয়।
উদাহরণ: AtomicInteger ব্যবহার
মাল্টি-থ্রেডিংয়ে সাধারণ integer ভেরিয়েবল ব্যবহার করলে Race Condition
public class RaceConditionExample {
private static int counter = 0;
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter++; // Race Condition হতে পারে
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final Counter Value: " + counter); // সঠিক মান নাও আসতে পারে
}
}
AtomicInteger দিয়ে Race Condition সমাধান
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicExample {
private static AtomicInteger counter = new AtomicInteger(0);
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.incrementAndGet(); // Thread-safe increment
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final Counter Value: " + counter.get()); // সঠিক মান
}
}
AtomicInteger ব্যবহার করার সুবিধা
- Thread Safety: কোনো সিঙ্ক্রোনাইজেশন প্রয়োজন হয় না।
- High Performance: লক-মুক্ত (lock-free) অপারেশন দ্বারা দ্রুত কাজ সম্পন্ন হয়।
- Concurrency Control: একাধিক থ্রেডের মধ্যে ডেটার সঠিকতা নিশ্চিত করে।
- Flexibility: বিভিন্ন মেথডের মাধ্যমে ডেটা ম্যানিপুলেশন সহজ হয়।
AtomicInteger এবং Synchronized এর তুলনা
| ফিচার | AtomicInteger | Synchronized |
|---|---|---|
| Thread Safety | নিশ্চিত | নিশ্চিত |
| Performance | উচ্চ, কারণ লক-মুক্ত | তুলনামূলক ধীর, কারণ লক ব্যবহৃত হয় |
| Complexity | সহজ এবং ব্যবহারযোগ্য | কোড জটিল হতে পারে |
| Usage Scope | শুধুমাত্র integer বা numeric ডেটার জন্য | সব ধরনের ডেটার জন্য |
AtomicInteger হল মাল্টি-থ্রেডিং পরিবেশে integer ভেরিয়েবল পরিচালনার জন্য একটি কার্যকর পদ্ধতি। এটি লক-মুক্ত, দ্রুত এবং সহজে ব্যবহারযোগ্য, যা ডেটার সঠিকতা এবং পারফরম্যান্স নিশ্চিত করে।