এটি কীভাবে সম্পন্ন হয় তার একটি ব্যাখ্যা এবং উদাহরণ এখানে। এমন কিছু অংশ আছে যা পরিষ্কার নয় me
উত্স সহ গিস্ট
সার্বজনীন
আরম্ভ:
থ্রেড সূচকগুলি একটি পরমাণু বর্ধিত ফ্যাশনে প্রয়োগ করা হয়। এটি একটি AtomicInteger
নাম ব্যবহার করে পরিচালিত হয় nextIndex
। এই সূচকগুলিকে একটি ThreadLocal
দৃষ্টান্তের মাধ্যমে থ্রেডগুলিতে বরাদ্দ করা হয়েছে যা পরবর্তী সূচকটি থেকে nextIndex
তা বাড়িয়ে এবং বৃদ্ধি করে নিজেকে সূচনা করে । প্রতিটি থ্রেডের সূচক প্রথমবার পুনরুদ্ধার করার পরে এটি ঘটে। একজন ThreadLocal
গত ক্রম এই থ্রেড নির্মিত ট্র্যাক তৈরি করা হয়। এটি সূচিত হয়েছে ০. ক্রমযুক্ত কারখানার অবজেক্ট রেফারেন্সটি পাস এবং সঞ্চিত হয়। দুটি AtomicReferenceArray
দৃষ্টান্ত আকারের তৈরি হয় n
। টেল অবজেক্টটি প্রতিটি রেফারেন্সে বরাদ্দ করা হয়, Sequential
কারখানার সরবরাহ করা প্রাথমিক অবস্থায় শুরু করা হয় । n
অনুমোদিত সর্বোচ্চ থ্রেডের সংখ্যা number এই অ্যারেগুলির প্রতিটি উপাদান সংশ্লিষ্ট থ্রেড সূচকের সাথে 'সম্পর্কিত'।
পদ্ধতি প্রয়োগ করুন:
এটি সেই পদ্ধতিটি যা আকর্ষণীয় কাজ করে। এটি নিম্নলিখিতগুলি করে:
- এই অনুরোধের জন্য একটি নতুন নোড তৈরি করুন: আমার
- বর্তমান থ্রেডের সূচকে ঘোষনা অ্যারেতে এই নতুন নোডটি সেট করুন
তারপরে ক্রম লুপ শুরু হয়। বর্তমান আহবানটি ক্রমবর্ধমান হওয়া অবধি এটি চলতে থাকবে:
- এই থ্রেড দ্বারা নির্মিত সর্বশেষ নোডের ক্রম ব্যবহার করে ঘোষনা অ্যারেতে একটি নোড সন্ধান করুন। এই সম্পর্কে আরও পরে।
- যদি কোনও পদক্ষেপ 2 এ নোড পাওয়া যায় তবে এটি এখনও সিকোয়েন্সড হয় নি, এটি চালিয়ে যান, অন্যথায়, কেবলমাত্র বর্তমান অনুরোধের দিকে মনোনিবেশ করুন। এটি কেবলমাত্র অনুরোধ অনুযায়ী অন্য একটি নোডকে সহায়তা করার চেষ্টা করবে।
- পদক্ষেপ 3 এ যে কোনও নোড নির্বাচন করা হয়েছিল, শেষ সিকোয়েন্সড নোডের পরে এটি সিকোয়েন্স করার চেষ্টা চালিয়ে যান (অন্যান্য থ্রেড হস্তক্ষেপ করতে পারে)) সাফল্য নির্বিশেষে, বর্তমান থ্রেডগুলি শীর্ষস্থান অনুসারে ফিরে আসা ক্রমের জন্য রেফারেন্স সেট করুন
decideNext()
উপরে বর্ণিত নেস্টেড লুপের মূলটি হ'ল decideNext()
পদ্ধতি। এটি বুঝতে, আমাদের নোড শ্রেণীর দিকে তাকাতে হবে।
নোড ক্লাস
এই শ্রেণিটি দ্বিগুণ-সংযুক্ত তালিকায় নোডগুলি নির্দিষ্ট করে। এই শ্রেণিতে প্রচুর পদক্ষেপ নেই। বেশিরভাগ পদ্ধতি হ'ল সহজ পুনরুদ্ধার পদ্ধতি যা মোটামুটি স্ব-ব্যাখ্যামূলক হওয়া উচিত।
লেজ পদ্ধতি
এটি ০. এর ক্রম সহ একটি বিশেষ নোড উদাহরণ প্রদান করে simply এটি একটি স্থান-ধারক হিসাবে কাজ করে যতক্ষণ না কোনও অনুরোধ এটি প্রতিস্থাপন করে।
সম্পত্তি এবং সূচনা
seq
: অনুক্রমের নম্বর, -1 এ প্রারম্ভিক (অর্থহীন)
invocation
: আমন্ত্রণের মান apply()
। নির্মাণ উপর সেট।
next
: AtomicReference
ফরোয়ার্ড লিঙ্কের জন্য। একবার নির্ধারিত হয়ে গেলে, এটি কখনও পরিবর্তন করা হবে না
previous
: AtomicReference
সিকোয়েন্সিংয়ের উপর নির্ধারিত পিছনের লিঙ্কটির জন্য এবং এর দ্বারা সাফ করা হয়েছেtruncate()
পরবর্তী সিদ্ধান্ত নিন
এই পদ্ধতিটি নোডে কেবলমাত্র একটি তুচ্ছ তর্কযুক্ত is সংক্ষেপে, লিঙ্কযুক্ত তালিকার পরবর্তী নোড হিসাবে প্রার্থী হিসাবে একটি নোড দেওয়া হয়। compareAndSet()
যদি এটা রেফারেন্স নাল পদ্ধতি চেক করবে এবং তাই যদি, প্রার্থী রেফারেন্স সেট। যদি রেফারেন্সটি ইতিমধ্যে সেট করা থাকে তবে এটি কিছুই করে না। এই অপারেশনটি পারমাণবিক তাই একই মুহুর্তে দু'জন প্রার্থীর প্রস্তাব দেওয়া হলে কেবল একজনকেই নির্বাচন করা হবে। এটি গ্যারান্টি দেয় যে কেবলমাত্র একটি নোড পরের বার হিসাবে নির্বাচিত হবে। যদি প্রার্থী নোডটি নির্বাচিত হয় তবে এটির ক্রমটি পরবর্তী মানটিতে সেট করা হবে এবং এর আগের লিঙ্কটি এই নোডে সেট করা আছে।
ইউনিভার্সাল ক্লাসে ফিরে আসার পদ্ধতি প্রয়োগ করুন ...
decideNext()
আমাদের নোড বা announce
অ্যারের থেকে কোনও নোডের সাথে সর্বশেষ সিকোয়েন্সড নোড (যখন চেক করা হবে) ডেকে নিয়ে যাওয়ার পরে দুটি সম্ভাব্য ঘটনা রয়েছে: ১. নোডটি সফলভাবে সিকোয়েন্সড হয়েছিল ২. কিছু থ্রেড এই থ্রেডটিকে প্রাক-খালি করা হয়েছে।
পরবর্তী পদক্ষেপটি এই অনুরোধের জন্য নোড তৈরি করেছে কিনা তা পরীক্ষা করা। এটি ঘটতে পারে কারণ এই থ্রেডটি সফলভাবে এটি সিকোয়েন্স করেছে বা অন্য কোনও থ্রেড এটিকে announce
অ্যারে থেকে তুলেছে এবং আমাদের জন্য এটি সিকোয়েন্সড করেছে। যদি এটি সিকোয়েন্সড না করা হয় তবে প্রক্রিয়াটি পুনরাবৃত্তি হয়। অন্যথায় কলটি এই থ্রেডের সূচকের জন্য ঘোষনা অ্যারে সাফ করে এবং অনুরোধের ফলাফলের মানটি ফিরিয়ে শেষ করে। ঘোষণার অ্যারেটি গ্যারান্টি হিসাবে পরিষ্কার করা হয়েছে যে নোডের আশেপাশে কোনও রেফারেন্স নেই যা নোডকে আবর্জনা সংগ্রহ করা থেকে বিরত রাখতে পারে এবং সেইজন্য সমস্ত নোডকে সেই বিন্দু থেকে লিঙ্ক তালিকায় রেখে দেবে he
পদ্ধতি মূল্যায়ন
এখন যেহেতু অনুরোধের নোডটি সাফল্যের সাথে সিকোয়েন্সড হয়েছে, অনুরোধটির মূল্যায়ন করা দরকার। এটি করার জন্য, প্রথম পদক্ষেপটি এটির পূর্ববর্তী অনুরোধগুলির মূল্যায়ন করা হয়েছে তা নিশ্চিত করা। যদি তারা না থাকে তবে এই থ্রেডটি অপেক্ষা করবে না তবে তা তাত্ক্ষণিকভাবে কাজটি করবে।
নিশ্চিতকরণের পদ্ধতি
ensurePrior()
পদ্ধতি যুক্ত তালিকা পূর্ববর্তী নোড চেক করে কাজ করে। যদি এটির রাজ্য সেট না করা থাকে তবে পূর্ববর্তী নোডটি মূল্যায়ন করা হবে। নোড যে এটি পুনরাবৃত্তি। পূর্ববর্তী নোডের পূর্বে নোডটি যদি মূল্যায়ন না করা হয় তবে এটি সেই নোডের জন্য মূল্যায়ন এবং আরও অনেক কিছু বলবে।
পূর্ববর্তী নোডের একটি রাষ্ট্র রয়েছে বলে জানা গেছে, আমরা এই নোডকে মূল্যায়ন করতে পারি। শেষ নোডটি পুনরুদ্ধার করা হয় এবং স্থানীয় ভেরিয়েবলের জন্য বরাদ্দ করা হয়। যদি এই রেফারেন্সটি নাল হয় তবে এর অর্থ হ'ল অন্য কোনও থ্রেড এটিকে প্রাক-খালি করেছে এবং ইতিমধ্যে এই নোডকে মূল্যায়ন করেছে; এটি স্থিতি স্থাপন। অন্যথায়, পূর্ববর্তী নোডের রাজ্যটি Sequential
এই নোডের অনুরোধের সাথে অবজেক্টের প্রয়োগ পদ্ধতিতে পাস করা হয় । প্রত্যাবর্তিত রাজ্যটি নোডে সেট করা হয় এবং truncate()
পদ্ধতিটি বলা হয়, নোড থেকে পিছনের লিঙ্কটি সাফ করে কারণ এটির আর প্রয়োজন নেই।
মুভফওয়ারওয়ার্ড পদ্ধতি
সরানো এগিয়ে যাওয়ার পদ্ধতিটি যদি ইতিমধ্যে আরও কিছু কিছুতে ইশারা না করে থাকে তবে সমস্ত নোটকে এই নোডে স্থানান্তরিত করার চেষ্টা করবে। এটি নিশ্চিত করার জন্য যে কোনও থ্রেড কল করা বন্ধ করে দিলে, এর মাথাটি কোনও নোডের রেফারেন্স ধরে রাখবে না যার দরকার নেই। compareAndSet()
পদ্ধতি নিশ্চিত আমরা কেবল নোড আপডেট যদি অন্য কিছু থ্রেড এটা যেহেতু এটি পুনরুদ্ধার করা হয়েছে পরিবর্তন হয়নি করতে হবে।
অ্যারে এবং সহায়তা ঘোষণা করুন
কেবলমাত্র লক-মুক্তের বিপরীতে এই পদ্ধতির অপেক্ষা-মুক্ত করার মূল চাবিকাঠিটি আমরা ধরে নিতে পারি না যে থ্রেড শিডিয়ুলার যখন প্রয়োজন তখন প্রতিটি থ্রেডকে অগ্রাধিকার দেবে। যদি প্রতিটি থ্রেড কেবল নিজের নিজস্ব নোডগুলি সিকোয়েন্স করার চেষ্টা করে তবে এটি সম্ভবত যে কোনও থ্রেড ক্রমাগত লোডের নিচে প্রাক-খালি করা যেতে পারে। এই সম্ভাবনার জন্য অ্যাকাউন্ট করতে প্রতিটি থ্রেড প্রথমে অন্যান্য থ্রেডগুলিকে 'সহায়তা' করার চেষ্টা করবে যা অনুক্রম হতে পারে না।
মূল ধারণাটি হ'ল প্রতিটি থ্রেড সফলভাবে নোড তৈরি করার সাথে সাথে নির্ধারিত ক্রমগুলি একঘেয়েভাবে বৃদ্ধি পাচ্ছে। যদি কোনও থ্রেড বা থ্রেড ক্রমাগতভাবে অন্য থ্রেডটিকে প্রাক-শূন্য করে চলেছে তবে announce
অ্যারেতে অনিবার্য নোডগুলি সন্ধানের জন্য সূচকটি এগিয়ে যাবে। এমনকি বর্তমানে প্রদত্ত নোডটিকে সিক্যুয়েন্স করার চেষ্টা করা প্রতিটি থ্রেড অন্য ধারাবাহিকভাবে ক্রমাগত প্রাক খালি করা থাকলেও শেষ পর্যন্ত সমস্ত থ্রেড সেই নোডটিকে সিক্যুয়েন্স করার চেষ্টা করবে। উদাহরণস্বরূপ, আমরা তিনটি থ্রেড সহ একটি উদাহরণ তৈরি করব।
শুরুতে, তিনটি থ্রেডের মাথা এবং ঘোষিত উপাদানগুলি tail
নোডের দিকে নির্দেশ করা হয় । lastSequence
প্রতিটি থ্রেড জন্য 0।
এই মুহুর্তে, অনুরোধের মাধ্যমে থ্রেড 1 কার্যকর করা হয়। এটি তার শেষ সিকোয়েন্স (শূন্য) এর জন্য ঘোষিত অ্যারেটি পরীক্ষা করে যা বর্তমানে নড যা এটি সূচিতে নির্ধারিত হয়। এটি নোডকে সিক্যুয়েন্স করে এটি lastSequence
1 এ সেট করা হয়।
থ্রেড 2 এখন একটি অনুরোধের সাথে কার্যকর করা হয়, এটি শেষ সিকোয়েন্স (শূন্য) এ ঘোষণার অ্যারেটি পরীক্ষা করে এবং দেখে যে এটির সাহায্যের প্রয়োজন নেই এবং তাই এটি অনুরোধের ক্রমটিভ করার চেষ্টা করে। এটি সফল হয় এবং এখন এটি lastSequence
2 এ সেট করা আছে।
থ্রেড 3 এখন কার্যকর করা হয়েছে এবং এটি এটি দেখতেও পেল যে নোডটি announce[0]
ইতিমধ্যে সিকোয়েন্সড এবং সিকোয়েন্সগুলি এটি নিজস্ব অনুরোধ। এটি lastSequence
এখন 3 এ সেট করা হয়েছে।
এখন থ্রেড 1 আবার প্রার্থনা করা হয়। এটি সূচী 1 এ ঘোষণার অ্যারেটি পরীক্ষা করে এবং এটি ইতিমধ্যে সিকোয়েন্সড অবস্থায় রয়েছে। একসাথে, থ্রেড 2 টি চালু করা হয়েছে। এটি সূচক 2 এ ঘোষণার অ্যারেটি পরীক্ষা করে এবং এটি ইতিমধ্যে সিকোয়েন্সড রয়েছে। থ্রেড 1 এবং থ্রেড 2 উভয়ই এখন তাদের নিজস্ব নোডকে সিকোয়েন্স করার চেষ্টা করে। থ্রেড 2 জিতে এবং এটি ক্রয়ের অনুরোধ করে। এটি lastSequence
৪ এ সেট করা হয়েছে ইতিমধ্যে থ্রেড তিনটি চালু করা হয়েছে। এটি সূচকটি এটি পরীক্ষা করে lastSequence
(আধুনিক 3) এবং এটি দেখতে পেয়েছে যে নোডটি announce[0]
ক্রমযুক্ত হয়নি। থ্রেড 2 আবার একই সাথে অনুরোধ করা হয়েছিল যে থ্রেড 1 এর দ্বিতীয় চেষ্টাতে রয়েছে। থ্রেড ঘথ্রেড 2announce[1]
দ্বারা সবে নির্মিত নোডটিতে একটি অনিবার্য প্রার্থনা সন্ধান করে । এটি থ্রেড 2 এর অনুরোধটিকে সিকোয়েন্স করার চেষ্টা করে এবং সফল হয়। থ্রেড 2 এটির নিজস্ব নোড খুঁজে পেয়েছে এবং এটি ক্রমযুক্ত হয়েছে। এটি 5 এর মধ্যে সেট হয়েছে Th থ্রেড 3 এর পরে অনুরোধ করা হয়েছে এবং খুঁজে পাওয়া যায় যে 1 টি থ্রেড থাকা নোডটি এখনও ক্রমযুক্ত নয় এবং এটি করার চেষ্টা করে। ইতিমধ্যে থ্রেড 2 টিও শুরু করা হয়েছে এবং থ্রেড 3 টি প্রাক-শূন্য করে দেওয়া হয়েছে এটি এটি নোডটিকে সিক্যুয়েন্স করে এটি 6 এ নির্ধারণ করে ।announce[1]
lastSequence
announce[0]
lastSequence
দরিদ্র থ্রেড ঘ । যদিও থ্রেড 3 এটি সিক্যুয়েন্স করার চেষ্টা করছে, উভয় থ্রেডটি নিয়মিতভাবে নিয়মিতভাবে ব্যর্থ হয়েছে th কিন্তু এই মুহুর্তে। থ্রেড 2 এখন ইঙ্গিত করছে announce[0]
(6 মড 3)। তিনটি থ্রেড একই অনুরোধটি ক্রমের চেষ্টা করতে প্রস্তুত। কোন থ্রেড সফল হয় তা বিবেচনা না করে, পরবর্তী নোডটি ক্রমযুক্ত হওয়া থ্রেড 1 এর অপেক্ষা অপেক্ষার অর্থ নোড দ্বারা রেফারেন্স করা হবে announce[0]
।
এটি অনিবার্য। থ্রেডগুলি প্রাক-খালি করার জন্য, অন্যান্য থ্রেডগুলি অবশ্যই নোডগুলি সিকোয়েন্সিং করা উচিত এবং তারা এটি করার সাথে সাথে তারা ক্রমাগত তাদের lastSequence
সামনের দিকে এগিয়ে যাবে। যদি প্রদত্ত থ্রেডের নোডটি ক্রমাগত ধারাবাহিক না হয়, অবশেষে সমস্ত থ্রেডগুলি ঘোষনা অ্যারেতে সূচকটির দিকে নির্দেশ করবে। যে নোডটি সাহায্যের চেষ্টা করছে সেটিকে ক্রমবর্ধমান না করা পর্যন্ত কোনও থ্রেড আর কিছু করবে না, সবচেয়ে খারাপ পরিস্থিতিটি হ'ল সমস্ত থ্রেড একই অনিচ্ছাকৃত নোডের দিকে নির্দেশ করছে। অতএব, যে কোনও অনুরোধের অনুক্রমের জন্য প্রয়োজনীয় সময়টি থ্রেডের সংখ্যার ফাংশন এবং ইনপুটটির আকার নয়।