Synchronization এবং Locking mechanisms হল multithreading প্রোগ্রামিং এর গুরুত্বপূর্ণ কনসেপ্ট, যা একাধিক থ্রেডের মধ্যে ডেটার অ্যাক্সেস এবং কনকারেন্সি (Concurrency) সঠিকভাবে নিয়ন্ত্রণ করতে ব্যবহৃত হয়। Objective-C তে সিঙ্ক্রোনাইজেশন এবং লকিং ব্যবহৃত হয় যাতে একাধিক থ্রেড একই ডেটা বা রিসোর্স অ্যাক্সেস করার সময় কোনও ধরনের কনফ্লিক্ট বা ডেটা কনসিস্টেন্সি সমস্যা না হয়।
এখানে Synchronization এবং Locking Mechanisms এর ব্যবহারিক উদাহরণ এবং তাদের কাজের বিস্তারিত আলোচনা করা হয়েছে।
1. Synchronization (সিঙ্ক্রোনাইজেশন)
Synchronization হল এমন একটি প্রক্রিয়া যা একাধিক থ্রেডের মধ্যে কনফ্লিক্ট এড়াতে ডেটার অ্যাক্সেস নিয়ন্ত্রণ করে। যখন একাধিক থ্রেড একটি কমন রিসোর্স (যেমন: ভেরিয়েবল, অ্যারে, ডিকশনারি ইত্যাদি) অ্যাক্সেস করে, তখন synchronization নিশ্চিত করে যে এক সময় শুধুমাত্র একটি থ্রেড সেই রিসোর্স অ্যাক্সেস করবে এবং অন্যথায় ডেটা কনসিস্টেন্সি সমস্যা হতে পারে।
Objective-C তে Synchronization
Objective-C তে synchronization করার জন্য @synchronized কিওয়ার্ড ব্যবহার করা হয়। এটি একটি ব্লক বা মেথডের চারপাশে থাকে এবং নিশ্চিত করে যে এক সময় শুধুমাত্র একটি থ্রেড সেই ব্লক বা মেথড এক্সিকিউট করতে পারে।
@synchronized এর সিনট্যাক্স:
@synchronized(object) {
// Critical section
// Only one thread can access this block at a time
}object: এটি সাধারণত সেই রিসোর্সের রেফারেন্স হয় যা আপনি সিঙ্ক্রোনাইজ করতে চান (যেমন: মেম্বার ভেরিয়েবল বা অবজেক্ট)।- Critical section: এই কোড ব্লকে শুধু একটি থ্রেড এক্সিকিউট করতে পারবে, যখন অন্য থ্রেড একই কোড ব্লক এক্সিকিউট করার চেষ্টা করবে তখন তাকে অপেক্ষা করতে হবে।
উদাহরণ:
#import <Foundation/Foundation.h>
@interface Counter : NSObject
@property int count;
- (void) incrementCount;
@end
@implementation Counter
- (void) incrementCount {
@synchronized(self) { // Synchronizing access to `count`
_count++; // Critical section: modifying `count`
NSLog(@"Current count: %d", _count);
}
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Counter *counter = [[Counter alloc] init];
// Multiple threads trying to increment the count
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[counter incrementCount];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[counter incrementCount];
});
// Wait for threads to finish
[[NSRunLoop currentRunLoop] run];
}
return 0;
}ব্যাখ্যা:
- এখানে,
@synchronized(self)দিয়েcountভেরিয়েবলটির অ্যাক্সেস সিঙ্ক্রোনাইজ করা হয়েছে। অর্থাৎ, এক থ্রেড যখনincrementCountমেথড এক্সিকিউট করছে, অন্য থ্রেড সেই মেথডে প্রবেশ করতে পারবে না। dispatch_asyncব্যবহার করে দুটি থ্রেডের মাধ্যমেcountভেরিয়েবলটি পরিবর্তন করা হয়েছে, কিন্তু@synchronizedনিশ্চিত করেছে যে এক সময় শুধুমাত্র একটি থ্রেডcountভেরিয়েবলটি অ্যাক্সেস করবে।
2. Locking Mechanisms (লকিং মেকানিজমস)
Locking হল এমন একটি প্রক্রিয়া যা একটি থ্রেডকে অন্য থ্রেডের কাজ শেষ না হওয়া পর্যন্ত একটি রিসোর্স অ্যাক্সেস করতে বাধা দেয়। Objective-C তে বেশ কয়েকটি লকিং মেকানিজম রয়েছে, যার মাধ্যমে থ্রেডের সিঙ্ক্রোনাইজেশন নিশ্চিত করা যায়। প্রধান দুটি লকিং মেকানিজম হল:
NSLock
NSLock একটি সিঙ্ক্রোনাইজেশন টুল যা থ্রেড সেফটি নিশ্চিত করার জন্য ব্যবহার করা হয়। এটি শুধুমাত্র এক থ্রেডকে একটি ক্রিটিক্যাল সেকশনে প্রবেশ করতে দেয় এবং অন্য থ্রেডকে অপেক্ষা করায় যতক্ষণ না প্রথম থ্রেড কাজটি শেষ করে।
NSLock এর ব্যবহার:
#import <Foundation/Foundation.h>
@interface Counter : NSObject
@property int count;
@property (strong) NSLock *lock;
- (void) incrementCount;
@end
@implementation Counter
- (instancetype)init {
self = [super init];
if (self) {
_lock = [[NSLock alloc] init]; // Lock initialization
}
return self;
}
- (void) incrementCount {
[self.lock lock]; // Lock acquired before critical section
_count++; // Critical section
NSLog(@"Current count: %d", _count);
[self.lock unlock]; // Lock released after critical section
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Counter *counter = [[Counter alloc] init];
// Multiple threads trying to increment the count
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[counter incrementCount];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[counter incrementCount];
});
// Wait for threads to finish
[[NSRunLoop currentRunLoop] run];
}
return 0;
}ব্যাখ্যা:
- NSLock ব্যবহার করা হয়েছে, যাতে এক সময় একটি থ্রেড
countভেরিয়েবলটি অ্যাক্সেস করতে পারে। থ্রেড যখনincrementCountমেথডে প্রবেশ করে, তখন এটিlockনেয় এবং কাজ শেষেunlockকরে।
NSRecursiveLock
NSRecursiveLock একটি লক টাইপ যা একই থ্রেডকে বার বার একই লক করতে অনুমতি দেয়। এটি এমন পরিস্থিতিতে উপকারী, যেখানে একটি থ্রেডকে একটি ক্রিটিক্যাল সেকশনে পুনরায় প্রবেশ করতে হতে পারে।
3. Semaphore
Semaphore একটি কনকারেন্ট সিস্টেমের জন্য লকিং মেকানিজম হিসেবে কাজ করে। এটি একাধিক থ্রেডের মধ্যে একটি নির্দিষ্ট সংখ্যক রিসোর্স শেয়ার করার অনুমতি দেয়।
উদাহরণ:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // Semaphore with 1 resource
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // Wait for semaphore
NSLog(@"First task started");
sleep(2); // Simulating task
NSLog(@"First task finished");
dispatch_semaphore_signal(semaphore); // Signal the semaphore to allow other threads
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // Wait for semaphore
NSLog(@"Second task started");
sleep(2); // Simulating task
NSLog(@"Second task finished");
dispatch_semaphore_signal(semaphore); // Signal the semaphore to allow other threads
});
// Wait for threads to finish
[[NSRunLoop currentRunLoop] run];
}
return 0;
}ব্যাখ্যা:
dispatch_semaphore_waitএবংdispatch_semaphore_signalব্যবহার করে একটি সিঙ্ক্রোনাইজেশন প্রক্রিয়া তৈরি করা হয়েছে যাতে একসাথে দুটি থ্রেড একই রিসোর্স অ্যাক্সেস না করে।
সারাংশ
- Synchronization এবং Locking মেকানিজম থ্রেডের মধ্যে ডেটা অ্যাক্সেস সিঙ্ক্রোনাইজ এবং সুরক্ষিত করার জন্য ব্যবহৃত হয়।
- @synchronized: এটি একটি সহজ টুল যা ব্লকের ভিতরে থ্রেডের সিঙ্ক্রোনাইজেশন নিশ্চিত করে।
- NSLock: এটি একটি ক্লাস যা থ্রেড সেফটি নিশ্চিত করতে একে একে থ্রেডগুলিকে ক্রিটিক্যাল সেকশনে প্রবেশ করতে দেয়।
- Semaphore: এটি একটি কনকারেন্ট সিস্টেমে একাধিক থ্রেডের মধ্যে রিসোর্স শেয়ার করার জন্য ব্যবহৃত হয়।
এই সমস্ত মেকানিজম একসাথে ব্যবহার করে আমরা অ্যাসিনক্রোনাস এবং কনকারেন্ট কাজ করতে পারি, যেখানে একাধিক থ্রেড নিরাপদে কাজ করে এবং ডেটার সঠিকতা
বজায় থাকে।
Read more