থ্রেড হ্যান্ডেল

বাইন্ডারের থ্রেডিং মডেলটি স্থানীয় ফাংশন কলগুলিকে সহজতর করার জন্য ডিজাইন করা হয়েছে, যদিও সেই কলগুলি দূরবর্তী প্রক্রিয়ায় হতে পারে। বিশেষ করে, একটি নোড হোস্ট করা যেকোনো প্রক্রিয়ায় সেই প্রক্রিয়ায় হোস্ট করা নোডগুলিতে লেনদেন পরিচালনা করার জন্য এক বা একাধিক বাইন্ডার থ্রেডের একটি পুল থাকতে হবে।

সিঙ্ক্রোনাস এবং অ্যাসিনক্রোনাস লেনদেন

বাইন্ডার সিঙ্ক্রোনাস এবং অ্যাসিনক্রোনাস লেনদেন সমর্থন করে। নিম্নলিখিত বিভাগগুলিতে প্রতিটি লেনদেনের ধরণ কীভাবে সম্পাদিত হয় তা ব্যাখ্যা করা হয়েছে।

সমলয় লেনদেন

সিঙ্ক্রোনাস লেনদেনগুলি নোডে কার্যকর না হওয়া পর্যন্ত ব্লক করা হয় এবং কলকারী সেই লেনদেনের জন্য একটি উত্তর পান। নিম্নলিখিত চিত্রটি দেখায় যে কীভাবে একটি সিঙ্ক্রোনাস লেনদেন কার্যকর করা হয়:

সমকালীন লেনদেন।

চিত্র ১. সমকালীন লেনদেন।

একটি সিঙ্ক্রোনাস লেনদেন সম্পাদন করতে, বাইন্ডার নিম্নলিখিত কাজগুলি করে:

  1. টার্গেট থ্রেডপুলের (T2 এবং T3) থ্রেডগুলি ইনকামিং কাজের জন্য অপেক্ষা করার জন্য কার্নেল ড্রাইভারে কল করে।
  2. কার্নেল একটি নতুন লেনদেন গ্রহণ করে এবং লেনদেন পরিচালনা করার জন্য টার্গেট প্রক্রিয়ায় একটি থ্রেড (T2) জাগিয়ে তোলে।
  3. কলিং থ্রেড (T1) ব্লক করে এবং উত্তরের জন্য অপেক্ষা করে।
  4. লক্ষ্য প্রক্রিয়া লেনদেন সম্পাদন করে এবং একটি উত্তর প্রদান করে।
  5. টার্গেট প্রসেসের (T2) থ্রেডটি নতুন কাজের জন্য অপেক্ষা করার জন্য কার্নেল ড্রাইভারে ফিরে আসে।

অ্যাসিঙ্ক্রোনাস লেনদেন

অ্যাসিঙ্ক্রোনাস লেনদেন সম্পূর্ণ হওয়ার জন্য ব্লক করা হয় না; লেনদেন কার্নেলে পাস হওয়ার সাথে সাথে কলিং থ্রেডটি আনব্লক হয়ে যায়। নিম্নলিখিত চিত্রটি দেখায় যে কীভাবে একটি অ্যাসিঙ্ক্রোনাস লেনদেন কার্যকর করা হয়:

অ্যাসিঙ্ক্রোনাস লেনদেন।

চিত্র ২. অ্যাসিঙ্ক্রোনাস লেনদেন।

  1. টার্গেট থ্রেডপুলের (T2 এবং T3) থ্রেডগুলি ইনকামিং কাজের জন্য অপেক্ষা করার জন্য কার্নেল ড্রাইভারে কল করে।
  2. কার্নেল একটি নতুন লেনদেন গ্রহণ করে এবং লেনদেন পরিচালনা করার জন্য টার্গেট প্রক্রিয়ায় একটি থ্রেড (T2) জাগিয়ে তোলে।
  3. কলিং থ্রেড (T1) কার্যকর করা অব্যাহত রাখে।
  4. লক্ষ্য প্রক্রিয়া লেনদেন সম্পাদন করে এবং একটি উত্তর প্রদান করে।
  5. টার্গেট প্রসেসের (T2) থ্রেডটি নতুন কাজের জন্য অপেক্ষা করার জন্য কার্নেল ড্রাইভারে ফিরে আসে।

একটি সিঙ্ক্রোনাস বা অ্যাসিনক্রোনাস ফাংশন সনাক্ত করুন

AIDL ফাইলে oneway হিসেবে চিহ্নিত ফাংশনগুলি অ্যাসিঙ্ক্রোনাস। উদাহরণস্বরূপ:

oneway void someCall();

যদি কোনও ফাংশন oneway হিসেবে চিহ্নিত না থাকে, তাহলে এটি একটি সিঙ্ক্রোনাস ফাংশন, এমনকি যদি ফাংশনটি void ফেরত দেয়।

অ্যাসিঙ্ক্রোনাস লেনদেনের ক্রমিকীকরণ

বাইন্ডার যেকোনো একক নোড থেকে অ্যাসিঙ্ক্রোনাস লেনদেনকে সিরিয়ালাইজ করে। নিচের চিত্রটি দেখায় কিভাবে বাইন্ডার অ্যাসিঙ্ক্রোনাস লেনদেনকে সিরিয়ালাইজ করে:

অ্যাসিঙ্ক্রোনাস লেনদেনের ক্রমিকীকরণ।

চিত্র ৩. অ্যাসিঙ্ক্রোনাস লেনদেনের ক্রমিকীকরণ।

  1. টার্গেট থ্রেডপুলের (B1 এবং B2) থ্রেডগুলি ইনকামিং কাজের জন্য অপেক্ষা করার জন্য কার্নেল ড্রাইভারকে কল করে।
  2. একই নোডে (N1) দুটি লেনদেন (T1 এবং T2) কার্নেলে পাঠানো হয়।
  3. কার্নেল একটি নতুন লেনদেন গ্রহণ করে এবং যেহেতু তারা একই নোড (N1) থেকে আসে, তাই তাদের সিরিয়ালাইজ করে।
  4. একটি ভিন্ন নোড (N2) এর উপর আরেকটি লেনদেন কার্নেলে পাঠানো হয়।
  5. কার্নেল তৃতীয় লেনদেন গ্রহণ করে এবং লেনদেন পরিচালনা করার জন্য টার্গেট প্রক্রিয়ায় একটি থ্রেড (B2) জাগিয়ে তোলে।
  6. লক্ষ্য প্রক্রিয়াগুলি প্রতিটি লেনদেন সম্পাদন করে এবং একটি উত্তর প্রদান করে।

নেস্টেড লেনদেন

সিঙ্ক্রোনাস লেনদেন নেস্ট করা যেতে পারে; যে থ্রেড একটি লেনদেন পরিচালনা করছে তা একটি নতুন লেনদেন ইস্যু করতে পারে। নেস্টেড লেনদেনটি অন্য কোনও প্রক্রিয়ায় হতে পারে, অথবা আপনি যে প্রক্রিয়া থেকে বর্তমান লেনদেনটি পেয়েছেন সেই একই প্রক্রিয়ায় হতে পারে। এই আচরণটি স্থানীয় ফাংশন কলের অনুকরণ করে। উদাহরণস্বরূপ, ধরুন আপনার নেস্টেড ফাংশন সহ একটি ফাংশন আছে:

def outer_function(x):
    def inner_function(y):
        def inner_inner_function(z):

যদি এগুলো লোকাল কল হয়, তাহলে এগুলো একই থ্রেডে এক্সিকিউট করা হয়। বিশেষ করে, যদি inner_function এর কলারটি inner_inner_function বাস্তবায়নকারী নোড হোস্টিং প্রক্রিয়াও হয়, তাহলে inner_inner_function এর কল একই থ্রেডে এক্সিকিউট করা হয়।

নিচের চিত্রটি দেখায় কিভাবে বাইন্ডার নেস্টেড লেনদেন পরিচালনা করে:

নেস্টেড লেনদেন।

চিত্র ৪। নেস্টেড লেনদেন।

  1. থ্রেড A1 foo() চালানোর অনুরোধ করে।
  2. এই অনুরোধের অংশ হিসেবে, থ্রেড B1 bar() চালায় যা A একই থ্রেড A1 তে চালায়।

নিচের চিত্রটি থ্রেড এক্সিকিউশন দেখায় যদি bar() প্রয়োগকারী নোডটি ভিন্ন প্রক্রিয়ায় থাকে:

বিভিন্ন প্রক্রিয়ায় নেস্টেড লেনদেন।

চিত্র ৫। বিভিন্ন প্রক্রিয়ায় নেস্টেড লেনদেন।

  1. থ্রেড A1 foo() চালানোর অনুরোধ করে।
  2. এই অনুরোধের অংশ হিসেবে, থ্রেড B1 bar() চালায় যা অন্য একটি থ্রেড C1 তে চলে।

নিচের চিত্রটি দেখায় কিভাবে লেনদেন শৃঙ্খলের যেকোনো স্থানে থ্রেডটি একই প্রক্রিয়া পুনঃব্যবহার করে:

একটি থ্রেড পুনঃব্যবহার করে নেস্টেড লেনদেন।

চিত্র ৬। একটি থ্রেড পুনঃব্যবহার করে নেস্টেড লেনদেন।

  1. প্রক্রিয়া A প্রক্রিয়া B-তে ডাকে।
  2. প্রক্রিয়া B প্রক্রিয়া C-তে ডাকে।
  3. প্রক্রিয়া C তারপর প্রক্রিয়া A-তে একটি কল ব্যাক করে এবং কার্নেল প্রক্রিয়া A-তে থ্রেড A1 পুনরায় ব্যবহার করে যা লেনদেন শৃঙ্খলের অংশ।

অ্যাসিঙ্ক্রোনাস লেনদেনের ক্ষেত্রে, নেস্টিং কোনও ভূমিকা পালন করে না; ক্লায়েন্ট অ্যাসিঙ্ক্রোনাস লেনদেনের ফলাফলের জন্য অপেক্ষা করে না, তাই কোনও নেস্টিং হয় না। যদি অ্যাসিঙ্ক্রোনাস লেনদেনের হ্যান্ডলার সেই অ্যাসিঙ্ক্রোনাস লেনদেন জারি করা প্রক্রিয়াটিতে একটি কল করে, তাহলে সেই লেনদেনটি সেই প্রক্রিয়ার যেকোনো ফ্রি থ্রেডে পরিচালনা করা যেতে পারে।

অচলাবস্থা এড়িয়ে চলুন

নিচের চিত্রটি একটি সাধারণ অচলাবস্থা দেখায়:

সাধারণ অচলাবস্থা।

চিত্র ৭। সাধারণ অচলাবস্থা।

  1. প্রক্রিয়া A, mutex MA নেয় এবং B প্রক্রিয়া করার জন্য একটি বাইন্ডার কল (T1) করে যা mutex MB নেওয়ার চেষ্টা করে।
  2. একই সাথে, প্রক্রিয়া B mutex MB নেয় এবং A প্রক্রিয়া করার জন্য একটি বাইন্ডার কল (T2) করে যা mutex MA নেওয়ার চেষ্টা করে।

যদি এই লেনদেনগুলি ওভারল্যাপ হয়, তাহলে প্রতিটি লেনদেন সম্ভাব্যভাবে তাদের প্রক্রিয়ায় একটি মিউটেক্স নিতে পারে এবং অন্য প্রক্রিয়াটি একটি মিউটেক্স প্রকাশের জন্য অপেক্ষা করতে পারে, যার ফলে একটি অচলাবস্থা তৈরি হতে পারে।

বাইন্ডার ব্যবহার করার সময় অচলাবস্থা এড়াতে, বাইন্ডার কল করার সময় কোনও লক ধরে রাখবেন না।

লক অর্ডার করার নিয়ম এবং অচলাবস্থা

একটি একক এক্সিকিউশন পরিবেশের মধ্যে, লক অর্ডারিং নিয়মের মাধ্যমে প্রায়শই অচলাবস্থা এড়ানো যায়। যাইহোক, প্রক্রিয়াগুলির মধ্যে এবং কোডবেসের মধ্যে কল করার সময়, বিশেষ করে কোড আপডেট হওয়ার সাথে সাথে, একটি অর্ডারিং নিয়ম বজায় রাখা এবং সমন্বয় করা অসম্ভব।

একক মিউটেক্স এবং অচলাবস্থা

নেস্টেড লেনদেনের মাধ্যমে, প্রক্রিয়া B সরাসরি প্রক্রিয়া A-তে একই থ্রেডে একটি মিউটেক্স ধারণ করে ফিরে যেতে পারে। অতএব, অপ্রত্যাশিত পুনরাবৃত্তির কারণে, একটি একক মিউটেক্সের সাথে একটি অচলাবস্থা তৈরি করা সম্ভব।

অ্যাসিঙ্ক্রোনাস কল এবং ডেডলক

যদিও অ্যাসিঙ্ক্রোনাস বাইন্ডার কলগুলি সম্পূর্ণ হওয়ার জন্য ব্লক করা হয় না, তবুও অ্যাসিঙ্ক্রোনাস কলগুলির জন্য আপনার লক ধরে রাখা এড়ানো উচিত। যদি আপনি একটি লক ধরে রাখেন, তাহলে যদি একটি ওয়ান-ওয়ে কল দুর্ঘটনাক্রমে একটি সিঙ্ক্রোনাস কলে পরিবর্তিত হয় তবে আপনার লকিং সমস্যা হতে পারে।

একক বাইন্ডার থ্রেড এবং ডেডলক

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

থ্রেডপুলের আকার কনফিগার করুন

যখন কোনও পরিষেবার একাধিক ক্লায়েন্ট থাকে, তখন থ্রেডপুলে আরও থ্রেড যুক্ত করলে বিতর্ক কমতে পারে এবং সমান্তরালে আরও কল পরিবেশন করা যায়। সঠিকভাবে কনকারেন্সি মোকাবেলা করার পরে, আপনি আরও থ্রেড যুক্ত করতে পারেন। আরও থ্রেড যুক্ত করার ফলে এমন একটি সমস্যা হতে পারে যা কিছু থ্রেড শান্ত কাজের চাপের সময় ব্যবহার নাও করতে পারে।

থ্রেডগুলি চাহিদা অনুযায়ী তৈরি হয় যতক্ষণ না কনফিগার করা সর্বোচ্চ। একটি বাইন্ডার থ্রেড তৈরি হওয়ার পর, এটি হোস্টিং প্রক্রিয়া শেষ না হওয়া পর্যন্ত এটি জীবিত থাকে।

libbinder লাইব্রেরিতে ডিফল্ট ১৫টি থ্রেড থাকে। এই মান পরিবর্তন করতে setThreadPoolMaxThreadCount ব্যবহার করুন:

using ::android::ProcessState;
ProcessState::self()->setThreadPoolMaxThreadCount(size_t maxThreads);