Actor হল একটি টাইপ যা Swift 5.5+-এ প্রবর্তিত হয়েছে যা ভাষা স্তরে ডেটা রেসের সমস্যা সমাধান করে। ম্যানুয়াল লক এবং DispatchQueue কিউগুলির বিপরীতে, actor স্বয়ংক্রিয়ভাবে তার অবস্থাকে বিচ্ছিন্ন করে এবং এতে অ্যাক্সেস সিঙ্ক্রোনাইজ করে। এর মানে হল যে দুটি থ্রেড একই সাথে একটি actor টাইপের একই প্রপার্টি পরিবর্তন করতে পারে না, যা ডেভেলপারের পক্ষ থেকে অতিরিক্ত প্রচেষ্টা ছাড়াই রেস কন্ডিশন দূর করে। প্রক্রিয়াটি actor-আইসোলেশন ধারণার উপর ভিত্তি করে, যেখানে কম্পাইলার actor-এর প্রপার্টি এবং মেথডগুলিতে অ্যাক্সেস ট্র্যাক করে। Apple, 2025 অনুসারে, actor মডেল Swift-এর কনকারেন্সি সিস্টেমের একটি মৌলিক অংশ।
মুখ্য বিষয়
Actor হল একটি রেফারেন্স টাইপ, ক্লাসের অনুরূপ, কিন্তু ডেটা রেসের বিরুদ্ধে স্বয়ংক্রিয় সুরক্ষা সহ। এটি Swift 5.5-এ async/await এবং Task-এর সাথে কনকারেন্সি সিস্টেমের অংশ হিসেবে প্রবর্তিত হয়েছিল। একটি actor গ্যারান্টি দেয় যে তার পরিবর্তনযোগ্য অবস্থা স্পষ্ট সিঙ্ক্রোনাইজেশন ছাড়া বিভিন্ন থ্রেড থেকে একসাথে কখনও পড়া বা লেখা হবে না।
একটি actor ঘোষণা করতে, actor কীওয়ার্ড ব্যবহার করা হয় যার পরে তার সদস্যদের সাথে কার্লি ব্রেস আসে। সিনট্যাক্টিকভাবে, actor একটি ক্লাসের মতো দেখায়, কিন্তু এর আচরণ মৌলিকভাবে আলাদা।
actor BankAccount {
private var balance: Double
init(initialBalance: Double) {
self.balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
}
func getBalance() -> Double {
return balance
}
}
কম্পাইলার স্বয়ংক্রিয়ভাবে সমস্ত actor প্রপার্টি এবং মেথডকে বিচ্ছিন্ন করে যাতে সেগুলি শুধুমাত্র actor কনটেক্সট-এর মধ্যে অ্যাক্সেসযোগ্য হয়। actor-এর বাইরে থেকে balance অ্যাক্সেস করার চেষ্টা করার সময়, কম্পাইলার একটি ত্রুটি তৈরি করবে যদি কলটি async হিসাবে চিহ্নিত না হয়।
ডেটা আইসোলেশন হল actor-এর মূল ধারণা। একটি actor actor নির্বাহক প্রক্রিয়ার মাধ্যমে তার অবস্থায় পারস্পরিক একচেটিয়া অ্যাক্সেসের গ্যারান্টি দেয়। প্রতিটি actor-এর নিজস্ব নির্বাহক থাকে যা তার বিচ্ছিন্ন সদস্যদের সমস্ত অ্যাক্সেস ক্রমিকভাবে প্রক্রিয়া করে।
যখন actor-এর বাইরের কোড তার মেথড কল করে, তখন কলটি actor নির্বাহক কিউতে রাখা হয়। Actor একবারে শুধুমাত্র একটি কাজ সম্পাদন করে, রেসের অনুপস্থিতির গ্যারান্টি দেয়। যদি দুটি থ্রেড একসাথে deposit কল করে, দ্বিতীয় কলটি প্রথমটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করে।
let account = BankAccount(initialBalance: 1000.0)
// অ্যাসিঙ্ক্রোনাস কল — actor-এর বাইরে থেকে প্রয়োজন
await account.deposit(amount: 500.0)
let currentBalance = await account.getBalance()
actor মেথডের প্রতিটি কলের জন্য await প্রয়োজন কারণ actor অন্য কোনো কাজে ব্যস্ত থাকতে পারে। এটি কোনো বাগ নয়, বরং একটি সচেতন ডিজাইন যা রেস প্রতিরোধ করে। Swift অন্তর্নিহিতভাবে actor প্রপার্টির গেটার এবং সেটারগুলিকে async করে তোলে, তাই একটি প্রপার্টি পড়ার জন্যও await প্রয়োজন।
Actor এবং ক্লাস উভয়ই রেফারেন্স টাইপ, কিন্তু মাল্টিথ্রেডেড পরিবেশে তাদের আচরণ নাটকীয়ভাবে আলাদা। ক্লাস রেসের বিরুদ্ধে কোনো স্বয়ংক্রিয় সুরক্ষা প্রদান করে না, যেখানে actor টাইপ সিস্টেমের মাধ্যমে কম্পাইলার স্তরে এটি এম্বেড করে।
| বৈশিষ্ট্য | Actor | Class |
|---|---|---|
| রেস সুরক্ষা | স্বয়ংক্রিয়, কম্পাইলার স্তরে | ম্যানুয়াল সিঙ্ক্রোনাইজেশন প্রয়োজন |
| প্রপার্টি অ্যাক্সেস | শুধুমাত্র বাইরে থেকে await-এর মাধ্যমে | সরাসরি, সিঙ্ক্রোনাইজেশন ছাড়া |
| উত্তরাধিকার | শুধুমাত্র অন্যান্য actors থেকে | স্ট্যান্ডার্ড ক্লাস-ভিত্তিক |
| প্রটোকল অনুরূপতা | প্রটোকল অনুসরণ করতে পারে | স্ট্যান্ডার্ড |
| কর্মক্ষমতা | আইসোলেশনের সাথে কম ওভারহেড | সিঙ্ক্রোনাইজেশন ছাড়া দ্রুততর |
একটি actor শুধুমাত্র অন্য actor থেকে উত্তরাধিকার পেতে পারে এবং ক্লাস থেকে উত্তরাধিকার পেতে পারে না। এটি ইচ্ছাকৃত কারণ ক্লাসে actor আইসোলেশন প্রক্রিয়ার অভাব রয়েছে এবং টাইপ মিশ্রিত করলে নিরাপত্তা গ্যারান্টি ভেঙে যাবে।
actor SavingsAccount: BankAccount {
func applyInterest(rate: Double) {
let interest = balance * rate
balance += interest
}
}
অ্যাসিঙ্ক্রোনাস কলগুলি বাহ্যিক কোড থেকে actor-এর সাথে ইন্টারঅ্যাক্ট করার প্রক্রিয়া। যেহেতু actor তার অবস্থাকে বিচ্ছিন্ন করে, বাইরে থেকে তার সদস্যদের যে কোনো অ্যাক্সেসের জন্য await প্রয়োজন। এটি Swift-কে গ্যারান্টি দিতে দেয় যে কলিং কোড থ্রেডটি ব্লক করে না এবং actor অন্যান্য অনুরোধ প্রক্রিয়া করতে পারে।
ঘোষিত actor টাইপ ছাড়াও, Swift গ্লোবাল actors সমর্থন করে — @MainActor অ্যাট্রিবিউট, যা ক্লাস, প্রপার্টি বা মেথডকে মূল থ্রেডে এক্সিকিউটেবল হিসাবে চিহ্নিত করে। এটি iOS অ্যাপ্লিকেশনে UI কোডের জন্য বিশেষভাবে উপযোগী।
@MainActor
class ViewModel: ObservableObject {
@Published var title: String = ""
func updateTitle() {
// এই কোডটি মূল থ্রেডে চলার গ্যারান্টিযুক্ত
title = "New Title"
}
}
@MainActor ব্যবহার ম্যানুয়ালি DispatchQueue.main.async কল করার প্রয়োজনীয়তা দূর করে, কোড পরিষ্কার এবং নিরাপদ করে। কম্পাইলার নিশ্চিত করে যে মূল থ্রেডে সুইচ করা সঠিকভাবে ঘটে।
Nonisolated হল একটি কীওয়ার্ড যা actor-এর একটি মেথড বা গণনা করা প্রপার্টিকে অ-বিচ্ছিন্ন হিসাবে চিহ্নিত করার অনুমতি দেয়। এই ধরনের সদস্যদের actor-বিচ্ছিন্ন অবস্থায় অ্যাক্সেস নেই, তবে actor-এর বাইরে থেকে await ছাড়া কল করা যেতে পারে।
Nonisolated মেথডগুলি সেই গণনার জন্য উপযোগী যা actor-এর পরিবর্তনযোগ্য অবস্থার উপর নির্ভর করে না। উদাহরণস্বরূপ, formatBalance মেথড সরাসরি balance অ্যাক্সেস করে না, বরং শুধুমাত্র পাস করা মান ফর্ম্যাট করে — এই ধরনের মেথডকে nonisolated করা নিরাপদ।
actor BankAccount {
private var balance: Double = 0
nonisolated func formatBalance(amount: Double) -> String {
return "$\(amount)"
}
}
Nonisolated সদস্যরা সিঙ্ক্রোনাসভাবে সম্পাদিত হয় এবং await-এর প্রয়োজন হয় না। তবে, তারা সরাসরি actor-বিচ্ছিন্ন প্রপার্টি পড়তে পারে না। যদি কোনো nonisolated মেথডের actor থেকে মান প্রয়োজন হয়, তবে এটি প্যারামিটার হিসাবে পাস করা আবশ্যক।
Reentrancy হল একটি প্রক্রিয়া যা একটি অ্যাসিঙ্ক্রোনাস কলের অপেক্ষার সময় actor-এ পুনঃপ্রবেশের অনুমতি দেয়। Reentrancy ছাড়া, actor চিরতরে ডেডলক হতে পারে যদি তার একটি মেথড অন্যের জন্য অপেক্ষা করে যা পালাক্রমে প্রথমটির জন্য অপেক্ষা করে।
যখন actor-এর ভিতরের কোড await সম্পাদন করে, actor বর্তমান কাজটি স্থগিত করে এবং কিউতে থাকা অন্য একটি কাজ প্রক্রিয়া করতে পারে। await সম্পূর্ণ হওয়ার পরে, কাজটি পুনরায় শুরু হয়। এটি ডেডলক প্রতিরোধ করে তবে সতর্কতা প্রয়োজন: await পয়েন্টগুলির মধ্যে actor-এর অবস্থা পরিবর্তিত হতে পারে।
actor DataProcessor {
var cache: [Int: String] = [:]
func process(id: Int) async -> String {
if let cached = cache[id] {
return cached
}
// await — পুনঃপ্রবেশ বিন্দু
let result = await fetchData(id: id)
// await-এর পরে ক্যাশে পরিবর্তিত হতে পারে — পুনরায় পরীক্ষা করুন
cache[id] = result
return result
}
}
ডেভেলপারদের reentrancy বিবেচনায় নেওয়া উচিত এবং await পয়েন্টগুলির পরে actor-এর অবস্থা পরীক্ষা করা উচিত। একটি সাধারণ ভুল হল ধরে নেওয়া যে actor আইসোলেশন অ্যাসিঙ্ক্রোনাস সাসপেনশন পয়েন্ট জুড়ে persists। বাস্তবে, await এবং পরবর্তী স্টেটমেন্টের মধ্যে, অবস্থা প্রত্যাশিত থেকে ভিন্ন হতে পারে।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
Actor স্বয়ংক্রিয়ভাবে তার অবস্থাকে ডেটা রেস থেকে বিচ্ছিন্ন করে, বাহ্যিক অ্যাক্সেসের জন্য await প্রয়োজন। ক্লাস এই ধরনের সুরক্ষা প্রদান করে না — ডেভেলপার লক বা কিউয়ের মাধ্যমে সিঙ্ক্রোনাইজেশনের জন্য দায়ী। Actor শুধুমাত্র actor থেকে উত্তরাধিকার পায়, ক্লাস ক্লাস থেকে।
হ্যাঁ, একটি actor অন্য actor থেকে উত্তরাধিকার পেতে পারে। উপশ্রেণী পিতামাতার সমস্ত বিচ্ছিন্ন প্রপার্টি এবং মেথড পায়। Actor ক্লাস থেকে উত্তরাধিকার পেতে পারে না কারণ ক্লাসগুলিতে কম্পাইলার স্তরে actor আইসোলেশন প্রক্রিয়ার অভাব রয়েছে।
actor-isolated কনটেক্সট হল একটি কোড এলাকা যেখানে actor-এর পরিবর্তনযোগ্য অবস্থায় সরাসরি অ্যাক্সেস অনুমোদিত। বিচ্ছিন্ন হিসাবে চিহ্নিত (ডিফল্টরূপে) actor মেথডগুলির ভিতরে, await ছাড়া প্রপার্টি পড়া এবং লেখা যায়। কম্পাইলার আইসোলেশন সীমানা পরীক্ষা করে।
Actor থেকে ডেটা async মেথড-এর মাধ্যমে পাঠানো হয় যা Sendable টাইপ রিটার্ন করে, বা nonisolated মেথডের মাধ্যমে যা প্যারামিটার হিসাবে মান গ্রহণ করে। একটি async প্রপার্টিও তৈরি করা যেতে পারে যা Sendable স্ট্রাকচার হিসাবে actor-এর অবস্থার স্ন্যাপশট রিটার্ন করে।
হ্যাঁ, actor প্রটোকল অনুসরণ করতে পারে। যদি একটি প্রটোকলে বিচ্ছিন্ন প্রয়োজনীয়তা (actor-isolated) থাকে, সেগুলি স্বয়ংক্রিয়ভাবে actor-বিচ্ছিন্ন হয়ে যায়। প্রটোকলের async মেথডগুলির জন্য, isolated মার্কার ব্যবহার করে নির্দিষ্ট করা যেতে পারে যে সেগুলিকে একটি নির্দিষ্ট actor-এ কল করতে হবে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন