জাভা অ্যাপ্লিকেশনগুলিতে মাল্টি-থ্রেডিং এবং ডাটাবেসের সাথে সংযুক্ত থ্রেড পরিচালনা একটি গুরুত্বপূর্ণ বিষয়। যখন একাধিক থ্রেড একে অপরের সাথে সমন্বিতভাবে কাজ করে, তখন থ্রেড সিঙ্ক্রোনাইজেশন (Thread Synchronization) এবং লকিং (Locking) ব্যবস্থাগুলি অপরিহার্য হয়ে ওঠে। সঠিক সিঙ্ক্রোনাইজেশন এবং লকিং প্রয়োগ করলে ডাটাবেসে একাধিক থ্রেডের মাধ্যমে পরিচালিত ক্রিয়াকলাপ সুরক্ষিত এবং সঠিকভাবে সম্পন্ন হতে পারে।
Thread Synchronization কি?
Thread Synchronization হল একটি প্রযুক্তি, যার মাধ্যমে একাধিক থ্রেড একসাথে একাধিক কাজ করতে পারে, তবে কখনো একাধিক থ্রেড একই সম্পদ (যেমন ডাটাবেস রেকর্ড) অ্যাক্সেস বা পরিবর্তন করতে পারে না। এটি ডেডলক (Deadlock) এবং রেস কন্ডিশন (Race Condition) প্রতিরোধ করে।
জাভাতে Thread Synchronization কীভাবে কাজ করে?
জাভাতে, থ্রেড সিঙ্ক্রোনাইজেশন করার জন্য synchronized কিওয়ার্ড ব্যবহার করা হয়। যখন কোনো থ্রেড একটি সিঙ্ক্রোনাইজড মেথড অথবা ব্লক অ্যাক্সেস করে, তখন অন্যান্য থ্রেডরা সেই রিসোর্সে প্রবেশ করতে পারে না যতক্ষণ না প্রথম থ্রেডটি সম্পন্ন হয়। এটি শুধুমাত্র একসময় একটিমাত্র থ্রেডকে রিসোর্সটি অ্যাক্সেস করতে অনুমতি দেয়।
Locking Mechanisms in Database
ডাটাবেসে লকিং (Locking) ব্যবস্থাগুলি বিশেষভাবে গুরুত্বপূর্ণ যখন একাধিক ইউজার বা অ্যাপ্লিকেশন একসাথে ডাটাবেস রিসোর্স (যেমন টেবিল বা রেকর্ড) অ্যাক্সেস করে। লকিং ব্যবস্থাগুলি ডেটার ইন্টিগ্রিটি (Integrity) এবং অ্যাপ্লিকেশনের সঠিক কাজ নিশ্চিত করে।
ডাটাবেসে লকিং টাইপসমূহ:
- Row-Level Locking:
এটি ডাটাবেসে একটি নির্দিষ্ট রেকর্ড বা সারি লক করে। এতে একাধিক থ্রেড বা ইউজাররা একই টেবিলে কাজ করতে পারলেও শুধুমাত্র লক করা রেকর্ডটি পরিবর্তন করতে পারে। - Table-Level Locking:
টেবিল লকিংয়ের মাধ্যমে পুরো টেবিলই লক করা হয়। এতে কোনো ইউজার পুরো টেবিলের উপর এককভাবে কাজ করতে পারে, তবে অন্য কেউ সেই টেবিলের কোনো অংশে কাজ করতে পারবে না। - Deadlock:
এটি একটি অবস্থা যেখানে দুটি বা তার বেশি থ্রেড একে অপরকে ব্লক করে রেখে কাজ করার চেষ্টা করে। উদাহরণস্বরূপ, থ্রেড A এবং থ্রেড B একে অপরের লক করা রিসোর্সের জন্য অপেক্ষা করছে, যা ডেডলক সৃষ্টি করে।
জাভা MySQL ডাটাবেসে Synchronization এবং Locking ব্যবহারের উদাহরণ
ধরা যাক, আপনার একটি অ্যাপ্লিকেশন রয়েছে যেখানে একাধিক থ্রেড MySQL ডাটাবেসে একই টেবিলের উপর কাজ করছে। আপনি চাইছেন যে, এক সময় একটিমাত্র থ্রেড সেই রেকর্ডটি আপডেট করুক এবং অন্যরা অপেক্ষা করুক।
Thread Synchronization in Java with Database Access Example
নিচে একটি উদাহরণ দেওয়া হলো যেখানে থ্রেড সিঙ্ক্রোনাইজেশন এবং ডাটাবেস লকিং প্রয়োগ করা হয়েছে:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DatabaseSynchronizationExample { private static final Object lock = new Object(); public static void updateRecord(int recordId, String newValue) { synchronized (lock) { String url = "jdbc:mysql://localhost:3306/yourDatabase"; String username = "yourUsername"; String password = "yourPassword"; try (Connection conn = DriverManager.getConnection(url, username, password)) { // Row-level lock (FOR UPDATE) to lock the specific record String selectSQL = "SELECT * FROM yourTable WHERE id = ? FOR UPDATE"; try (PreparedStatement stmt = conn.prepareStatement(selectSQL)) { stmt.setInt(1, recordId); ResultSet rs = stmt.executeQuery(); if (rs.next()) { // Update the record String updateSQL = "UPDATE yourTable SET value = ? WHERE id = ?"; try (PreparedStatement updateStmt = conn.prepareStatement(updateSQL)) { updateStmt.setString(1, newValue); updateStmt.setInt(2, recordId); updateStmt.executeUpdate(); System.out.println("Record updated successfully."); } } } } catch (SQLException e) { e.printStackTrace(); } } } public static void main(String[] args) { Thread thread1 = new Thread(() -> updateRecord(1, "NewValue1")); Thread thread2 = new Thread(() -> updateRecord(1, "NewValue2")); thread1.start(); thread2.start(); } }ব্যাখ্যা:
- এখানে
synchronizedব্লক ব্যবহার করা হয়েছে যাতে একসময় একটিমাত্র থ্রেড MySQL ডাটাবেসে রেকর্ডটি আপডেট করতে পারে। FOR UPDATESQL ক্লজটি রো লেভেল লক প্রয়োগ করে, যা সেই নির্দিষ্ট রেকর্ডটি লক করে রাখে যতক্ষণ না থ্রেডটি সম্পন্ন হয়।
- এখানে
Database Locking with Table-Level Locking
String lockTableSQL = "LOCK TABLE yourTable WRITE"; String unlockTableSQL = "UNLOCK TABLES"; try (Connection conn = DriverManager.getConnection(url, username, password)) { // Lock the entire table try (PreparedStatement lockStmt = conn.prepareStatement(lockTableSQL)) { lockStmt.executeUpdate(); // Perform operations on the table String updateSQL = "UPDATE yourTable SET value = ? WHERE id = ?"; try (PreparedStatement updateStmt = conn.prepareStatement(updateSQL)) { updateStmt.setString(1, "NewValue"); updateStmt.setInt(2, 1); updateStmt.executeUpdate(); } // Unlock the table after operation try (PreparedStatement unlockStmt = conn.prepareStatement(unlockTableSQL)) { unlockStmt.executeUpdate(); } } } catch (SQLException e) { e.printStackTrace(); }ব্যাখ্যা:
LOCK TABLE yourTable WRITESQL ক্লজটি পুরো টেবিলটি লক করে রাখে, যার ফলে অন্য কোনো থ্রেড বা ইউজার সেই টেবিলের উপর কাজ করতে পারে না যতক্ষণ না টেবিল আনলক করা হয়।
Deadlock থেকে প্রতিরোধ
Deadlock পরিস্থিতি এড়াতে কিছু ভালো অনুশীলন রয়েছে:
- লক আর্ডার (Lock Ordering): সমস্ত থ্রেডের মধ্যে লক করার জন্য একটি নির্দিষ্ট কৌশল এবং সিকোয়েন্স বজায় রাখুন।
- টাইমআউট (Timeout): লক করার পর নির্দিষ্ট সময়ের মধ্যে কাজ না হলে লকটি ছেড়ে দিন এবং পুনরায় চেষ্টা করুন।
- থ্রেড প্রাধান্য (Thread Prioritization): থ্রেডগুলোর প্রাধান্য ঠিক করে কাজ করার ব্যবস্থা করুন।
সারাংশ
জাভা এবং MySQL ডাটাবেসের সাথে থ্রেড সিঙ্ক্রোনাইজেশন এবং লকিং ব্যবস্থার মাধ্যমে একাধিক থ্রেড বা ইউজারদের মধ্যে ডেটা নিরাপত্তা নিশ্চিত করা যায়। সিঙ্ক্রোনাইজেশন নিশ্চিত করে যে একসময় শুধুমাত্র একথ্রেডই ডাটাবেস রিসোর্স অ্যাক্সেস করতে পারে, আর লকিং মেকানিজমগুলি ডাটাবেসে ডেডলক এবং রেস কন্ডিশন প্রতিরোধে সাহায্য করে। Proper synchronization এবং locking প্রয়োগ করে ডাটাবেস অপারেশনগুলিকে আরো সুরক্ষিত এবং কার্যকরী করা সম্ভব।
Read more