Sync এবং Send Trait-এর সাহায্যে প্রসারণযোগ্য কনকারেন্সি (Extensible Concurrency)

আগ্রহজনকভাবে, Rust ল্যাংগুয়েজে কনকারেন্সির বৈশিষ্ট্য খুবই কম। এই চ্যাপ্টারে আমরা இதுவரை কনকারেন্সির প্রায় প্রতিটি বৈশিষ্ট্য নিয়ে আলোচনা করেছি সেগুলি standard library-এর অংশ, ল্যাংগুয়েজের নয়। কনকারেন্সি পরিচালনার জন্য আপনার বিকল্পগুলি কেবল ল্যাংগুয়েজ বা standard library-তে সীমাবদ্ধ নয়; আপনি নিজের কনকারেন্সি বৈশিষ্ট্য লিখতে পারেন বা অন্যদের লেখা বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন।

যাইহোক, দুটি কনকারেন্সি ধারণা ল্যাংগুয়েজে এমবেড করা আছে: std::marker-এর Sync এবং Send trait।

Send-এর মাধ্যমে থ্রেডগুলির মধ্যে Ownership স্থানান্তর করার অনুমতি

Send মার্কার trait টি নির্দেশ করে যে Send ইমপ্লিমেন্ট করা type-এর value-গুলির ownership থ্রেডগুলির মধ্যে স্থানান্তর করা যেতে পারে। প্রায় প্রতিটি Rust টাইপ Send, তবে কিছু ব্যতিক্রম রয়েছে, যার মধ্যে Rc<T> অন্তর্ভুক্ত: এটি Send হতে পারে না কারণ আপনি যদি একটি Rc<T> value ক্লোন করেন এবং ক্লোনের ownership অন্য থ্রেডে স্থানান্তর করার চেষ্টা করেন, তাহলে উভয় থ্রেড একই সময়ে reference count আপডেট করতে পারে। এই কারণে, Rc<T> single-threaded পরিস্থিতিতে ব্যবহারের জন্য ইমপ্লিমেন্ট করা হয়েছে যেখানে আপনি thread-safe পারফরম্যান্স পেনাল্টি দিতে চান না।

অতএব, Rust-এর type system এবং trait bound গুলি নিশ্চিত করে যে আপনি কখনই ভুল করে অনিরাপদভাবে থ্রেড জুড়ে একটি Rc<T> value পাঠাতে পারবেন না। Listing 16-14-এ যখন আমরা এটি করার চেষ্টা করেছি, তখন আমরা error পেয়েছিলাম the trait Send is not implemented for Rc<Mutex<i32>>। যখন আমরা Arc<T>-এ পরিবর্তন করেছি, যেটি Send, কোডটি compile হয়েছে।

Send type গুলি দ্বারা সম্পূর্ণরূপে গঠিত যেকোনো type স্বয়ংক্রিয়ভাবে Send হিসাবে চিহ্নিত হয়। Raw pointer গুলি বাদে প্রায় সমস্ত primitive type হল Send, যা নিয়ে আমরা Chapter 20-এ আলোচনা করব।

Sync-এর মাধ্যমে একাধিক থ্রেড থেকে অ্যাক্সেসের অনুমতি

Sync মার্কার trait টি নির্দেশ করে যে Sync ইমপ্লিমেন্ট করা type-টিকে একাধিক থ্রেড থেকে রেফারেন্স করা নিরাপদ। অন্য কথায়, যেকোনো type T হল Sync যদি &T ( T-তে একটি immutable reference) Send হয়, অর্থাৎ reference টি নিরাপদে অন্য থ্রেডে পাঠানো যেতে পারে। Send-এর মতোই, primitive type গুলি Sync, এবং সম্পূর্ণরূপে Sync type গুলি দ্বারা গঠিত type গুলিও Sync

smart pointer Rc<T>-ও Sync নয়, একই কারণে এটি Send নয়। RefCell<T> type (যা নিয়ে আমরা Chapter 15-এ আলোচনা করেছি) এবং সম্পর্কিত Cell<T> type-এর পরিবার Sync নয়। RefCell<T> runtime-এ যে borrow চেকিং করে তার ইমপ্লিমেন্টেশন thread-safe নয়। smart pointer Mutex<T> হল Sync এবং একাধিক থ্রেডের সাথে অ্যাক্সেস শেয়ার করতে ব্যবহার করা যেতে পারে যেমনটি আপনি “Sharing a Mutex<T> Between Multiple Threads”-এ দেখেছেন।

ম্যানুয়ালি Send এবং Sync ইমপ্লিমেন্ট করা Unsafe

যেহেতু Send এবং Sync trait দ্বারা গঠিত type গুলি স্বয়ংক্রিয়ভাবে Send এবং Sync হয়, তাই আমাদের ম্যানুয়ালি সেই trait গুলি ইমপ্লিমেন্ট করার প্রয়োজন নেই। মার্কার trait হিসাবে, তাদের ইমপ্লিমেন্ট করার জন্য কোনও মেথডও নেই। এগুলি কেবল কনকারেন্সি সম্পর্কিত ইনভেরিয়েন্টগুলি প্রয়োগ করার জন্য দরকারী।

এই trait গুলি ম্যানুয়ালি ইমপ্লিমেন্ট করার মধ্যে unsafe Rust কোড ইমপ্লিমেন্ট করা জড়িত। আমরা Chapter 20-এ unsafe Rust কোড ব্যবহার সম্পর্কে কথা বলব; আপাতত, গুরুত্বপূর্ণ তথ্য হল যে Send এবং Sync অংশ দ্বারা গঠিত নয় এমন নতুন concurrent type তৈরি করার জন্য safety গ্যারান্টিগুলি বজায় রাখার জন্য সতর্ক চিন্তাভাবনার প্রয়োজন। “The Rustonomicon”-এ এই গ্যারান্টিগুলি এবং কীভাবে সেগুলি বজায় রাখা যায় সে সম্পর্কে আরও তথ্য রয়েছে।

সারাংশ

এই বইয়ে আপনি কনকারেন্সির শেষ দেখা পাবেন না: সম্পূর্ণ পরবর্তী চ্যাপ্টারটি অ্যাসিঙ্ক্রোনাস প্রোগ্রামিংয়ের উপর ফোকাস করে এবং Chapter 21-এর প্রোজেক্টটি এখানে আলোচিত ছোট উদাহরণগুলির চেয়ে আরও বাস্তব পরিস্থিতিতে এই চ্যাপ্টারের ধারণাগুলি ব্যবহার করবে।

আগেই উল্লেখ করা হয়েছে, যেহেতু Rust কীভাবে কনকারেন্সি পরিচালনা করে তার খুব সামান্য অংশই ল্যাংগুয়েজের অংশ, তাই অনেক কনকারেন্সি সমাধান crate হিসাবে ইমপ্লিমেন্ট করা হয়। এগুলি standard library-এর চেয়ে দ্রুত বিকশিত হয়, তাই multithreaded পরিস্থিতিতে ব্যবহার করার জন্য বর্তমান, state-of-the-art crate-গুলির জন্য অনলাইনে সার্চ করতে ভুলবেন না।

Rust standard library মেসেজ পাসিংয়ের জন্য চ্যানেল এবং smart pointer type, যেমন Mutex<T> এবং Arc<T>, সরবরাহ করে যা concurrent পরিস্থিতিতে ব্যবহার করা নিরাপদ। type system এবং borrow চেকার নিশ্চিত করে যে এই সমাধানগুলি ব্যবহার করা কোডে ডেটা রেস বা অবৈধ রেফারেন্স থাকবে না। একবার আপনি আপনার কোড compile করতে পারলে, আপনি নিশ্চিন্ত থাকতে পারেন যে এটি অন্যান্য ল্যাংগুয়েজের সাধারণ hard-to-track-down বাগগুলি ছাড়াই আনন্দের সাথে একাধিক থ্রেডে চলবে। Concurrent প্রোগ্রামিং আর ভয় পাওয়ার মতো কোনও ধারণা নয়: এগিয়ে যান এবং আপনার program গুলিকে নির্ভয়ে concurrent করুন!