Atomic Classes হল Java এর java.util.concurrent.atomic প্যাকেজের একটি অংশ, যা low-level concurrency control নিশ্চিত করে। এটি মাল্টি-থ্রেডেড অ্যাপ্লিকেশনে thread-safe ডেটা ম্যানিপুলেশন করতে ব্যবহৃত হয়। Atomic Classes ব্যবহার করে lock-free এবং non-blocking concurrent data structures তৈরি করা যায়, যা performance এবং scalability উন্নত করে।
কনকারেন্ট ডেটা স্ট্রাকচার তৈরির জন্য Atomic Classes
Atomic Classes মূলত নিম্নলিখিত কাজগুলো নিশ্চিত করে:
- Atomic Operations: একাধিক থ্রেডের মধ্যে ডেটা ম্যানিপুলেশন সঠিক ও নিরাপদ রাখা।
- CAS (Compare-and-Swap): ডেটা আপডেট করার সময় race condition প্রতিরোধ করা।
- Non-blocking Synchronization: কোনো থ্রেড ব্লক না করেই ডেটা আপডেট নিশ্চিত করা।
Atomic Classes এর ধরন
১. AtomicInteger
একটি পূর্ণসংখ্যার মান থ্রেড-সেফ উপায়ে পরিচালনা করতে ব্যবহৃত হয়।
২. AtomicLong
long টাইপের ডেটা ম্যানিপুলেশন করতে ব্যবহৃত হয়।
৩. AtomicBoolean
একটি boolean মান পরিচালনার জন্য ব্যবহৃত হয়।
৪. AtomicReference
যেকোনো অবজেক্ট রেফারেন্স থ্রেড-সেফ উপায়ে পরিচালনার জন্য ব্যবহৃত হয়।
৫. AtomicStampedReference
একটি রেফারেন্স এবং এর সাথে একটি স্ট্যাম্প মান (যেমন সংস্করণ ট্র্যাকিং) পরিচালনার জন্য ব্যবহৃত হয়।
৬. AtomicMarkableReference
রেফারেন্সের সাথে একটি boolean চিহ্ন (mark) মেইনটেইন করতে ব্যবহৃত হয়।
Atomic Classes ব্যবহার করে কনকারেন্ট ডেটা স্ট্রাকচার তৈরি
১. Concurrent Stack (AtomicReference ব্যবহার)
AtomicReference ব্যবহার করে একটি thread-safe stack তৈরি করা যায়।
import java.util.concurrent.atomic.AtomicReference;
public class ConcurrentStack<T> {
private AtomicReference<Node<T>> head = new AtomicReference<>();
private static class Node<T> {
T value;
Node<T> next;
Node(T value, Node<T> next) {
this.value = value;
this.next = next;
}
}
// Push operation
public void push(T value) {
Node<T> newNode = new Node<>(value, null);
Node<T> currentHead;
do {
currentHead = head.get();
newNode.next = currentHead; // Link new node to current head
} while (!head.compareAndSet(currentHead, newNode)); // Atomic CAS operation
}
// Pop operation
public T pop() {
Node<T> currentHead;
Node<T> newHead;
do {
currentHead = head.get();
if (currentHead == null) {
return null; // Stack is empty
}
newHead = currentHead.next;
} while (!head.compareAndSet(currentHead, newHead)); // Atomic CAS operation
return currentHead.value;
}
}
ব্যবহার:
public class Main {
public static void main(String[] args) {
ConcurrentStack<Integer> stack = new ConcurrentStack<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack.pop()); // 3
System.out.println(stack.pop()); // 2
System.out.println(stack.pop()); // 1
}
}
২. Concurrent Queue (AtomicReference এবং AtomicStampedReference ব্যবহার)
AtomicStampedReference ব্যবহার করে একটি thread-safe queue তৈরি করা যায় যা ABA সমস্যা প্রতিরোধ করে।
import java.util.concurrent.atomic.AtomicStampedReference;
public class ConcurrentQueue<T> {
private static class Node<T> {
T value;
Node<T> next;
Node(T value) {
this.value = value;
}
}
private AtomicStampedReference<Node<T>> head, tail;
public ConcurrentQueue() {
Node<T> dummy = new Node<>(null);
head = new AtomicStampedReference<>(dummy, 0);
tail = new AtomicStampedReference<>(dummy, 0);
}
// Enqueue operation
public void enqueue(T value) {
Node<T> newNode = new Node<>(value);
Node<T> currentTail;
int[] stamp = new int[1];
do {
currentTail = tail.get(stamp);
} while (!tail.compareAndSet(currentTail, newNode, stamp[0], stamp[0] + 1));
currentTail.next = newNode; // Link new node
}
// Dequeue operation
public T dequeue() {
Node<T> currentHead;
Node<T> currentTail;
Node<T> nextNode;
int[] stamp = new int[1];
do {
currentHead = head.get(stamp);
currentTail = tail.get();
nextNode = currentHead.next;
if (currentHead == currentTail) {
if (nextNode == null) {
return null; // Queue is empty
}
tail.compareAndSet(currentTail, nextNode, stamp[0], stamp[0] + 1); // Advance tail
}
} while (!head.compareAndSet(currentHead, nextNode, stamp[0], stamp[0] + 1)); // Advance head
return nextNode.value;
}
}
ব্যবহার:
public class Main {
public static void main(String[] args) {
ConcurrentQueue<Integer> queue = new ConcurrentQueue<>();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
System.out.println(queue.dequeue()); // 1
System.out.println(queue.dequeue()); // 2
System.out.println(queue.dequeue()); // 3
}
}
Atomic Classes ব্যবহার করে ডেটা স্ট্রাকচারের সুবিধা
- Thread-safe: একাধিক থ্রেড ডেটা স্ট্রাকচারের উপর কাজ করলেও ডেটার সঠিকতা বজায় থাকে।
- Lock-free: কোনো লক বা মিউটেক্স ব্যবহার না করেও ডেটা আপডেট করা যায়।
- Performance: কম্প্লেক্স কনকারেন্সি মেকানিজমের তুলনায় এটি দ্রুত কাজ করে।
- ABA Problem Handling:
AtomicStampedReferenceব্যবহার করে ABA সমস্যা সমাধান করা যায়।
Atomic Classes এর সীমাবদ্ধতা
- Complexity: বড় এবং জটিল ডেটা স্ট্রাকচারে এটি পরিচালনা করা কঠিন।
- Overhead: CAS অপারেশনের বারবার ব্যর্থতা পারফরম্যান্স হ্রাস করতে পারে।
- Memory Management: Atomic Classes ব্যবহার করে তৈরি ডেটা স্ট্রাকচারের জন্য সঠিক মেমোরি ব্যবস্থাপনা প্রয়োজন।
Atomic Classes মাল্টি-থ্রেডেড অ্যাপ্লিকেশনে ডেটা ম্যানিপুলেশনের জন্য একটি কার্যকর সমাধান। এটি thread-safe, lock-free, এবং non-blocking ডেটা স্ট্রাকচার তৈরি করতে ব্যবহৃত হয়। উদাহরণস্বরূপ, Concurrent Stack এবং Queue তৈরিতে Atomic Classes ব্যবহার করা যেতে পারে, যা থ্রেডগুলোর মধ্যে race condition এবং deadlock সমস্যা সমাধান করে।
Read more