উত্তর:
একটি স্পিন লক হ'ল একসাথে দুই বা আরও বেশি প্রক্রিয়া দ্বারা কোনও ভাগ করা সংস্থান থেকে রক্ষা পাওয়ার উপায়। প্রথম প্রক্রিয়া যা রিসোর্সটি সংশোধন করার চেষ্টা করে লকটি "অর্জন" করে এবং সেই পথে চালিয়ে যায়, এটি সংস্থানটির জন্য যা প্রয়োজন তা করে। পরবর্তীকালে লকটি অর্জনের চেষ্টা করা অন্য যে কোনও প্রক্রিয়া বন্ধ হয়ে যায়; তাদের প্রথম জায়গায় প্রক্রিয়াটি প্রকাশের জন্য লকটির অপেক্ষায় "স্পিন ইন স্পিন" বলা হয়, এভাবে নাম স্পিন লক করা হয়।
লিনাক্স কার্নেলটি বিভিন্ন জিনিসের জন্য স্পিন লক ব্যবহার করে যেমন কোনও নির্দিষ্ট পেরিফেরিয়ায় ডেটা প্রেরণ করার সময়। বেশিরভাগ হার্ডওয়্যার পেরিফেরালগুলি একাধিক যুগপত স্টেট আপডেটগুলি হ্যান্ডেল করার জন্য ডিজাইন করা হয়নি। যদি দুটি পৃথক পরিবর্তন ঘটে থাকে তবে একজনকে অন্যটিকে কঠোরভাবে অনুসরণ করতে হবে, তারা ওভারল্যাপ করতে পারে না। একটি স্পিন লক প্রয়োজনীয় সুরক্ষা সরবরাহ করে এটি নিশ্চিত করে যে পরিবর্তনগুলি একবারে ঘটেছিল।
স্পিন লকগুলি একটি সমস্যা কারণ থ্রিনের সিপিইউ কোরকে অন্য কোনও কাজ করা থেকে কাটছে spin লিনাক্স কার্নেল এর অধীনে চলমান ব্যবহারকারীর স্পেস প্রোগ্রামগুলিতে মাল্টিটাস্কিং পরিষেবা সরবরাহ করার সময়, সাধারণ উদ্দেশ্যযুক্ত মাল্টিটাস্কিং সুবিধা কার্নেল কোডে প্রসারিত হয় না।
এই পরিস্থিতিটি পরিবর্তিত হচ্ছে, এবং লিনাক্সের বেশিরভাগ অস্তিত্বের জন্য। লিনাক্স ২.০-এর মাধ্যমে, কার্নেলটি প্রায় সম্পূর্ণরূপে একক-টাস্কিং প্রোগ্রাম ছিল: যখনই সিপিইউ কার্নেল কোড চালাচ্ছিল, কেবলমাত্র একটি সিপিইউ কোর ব্যবহার করা হত, কারণ সেখানে সমস্ত ভাগ করা সংস্থানগুলি রক্ষা করার জন্য একটি স্পিন লক ছিল, বিগ কার্নেল লক (বিকেএল) নামে পরিচিত called )। লিনাক্স ২.২ দিয়ে শুরু করে, বিকেএল ধীরে ধীরে অনেকগুলি স্বতন্ত্র তালায় বিভক্ত হয়ে গেছে যা প্রত্যেকে আরও বেশি মনোনিবেশিত শ্রেণীর সংস্থান রক্ষা করে। কার্নেল ২.6 সহ আজ, বিকেএল এখনও বিদ্যমান, তবে এটি কেবল সত্যিকারের পুরানো কোড দ্বারা ব্যবহৃত হয়েছে যা সহজেই আরও কিছু দানাদার লকটিতে সরানো যায় না। মাল্টিকোর বাক্সে প্রতিটি সিপিইউ কার্যকর কার্নেল কোড চালানো এখন যথেষ্ট সম্ভব।
বিকেএল ভেঙে ফেলার জন্য ইউটিলিটির সীমাবদ্ধতা রয়েছে কারণ লিনাক্স কার্নেলের সাধারণ মাল্টিটাস্কিংয়ের অভাব রয়েছে। যদি কোনও সিপিইউ কোর কার্নেল স্পিন লকটিতে ব্লক স্পিনিং হয়ে যায় তবে লকটি প্রকাশ না হওয়া পর্যন্ত এটি অন্য কোনও কাজ করার জন্য এটি পুনরায় চালু করা যাবে না। লকটি প্রকাশ না হওয়া পর্যন্ত এটি কেবল বসে এবং স্পিন করে।
স্পিন লক কার্যকরভাবে একটি দৈত্য 16-কোর বক্সকে একটি একক-কোর বাক্সে পরিণত করতে পারে, যদি কাজের চাপ এমন হয় যে প্রতিটি কোর সর্বদা একটি স্পিন লকের জন্য অপেক্ষা করে। এটি লিনাক্স কার্নেলের স্কেলিবিলিটির মূল সীমা: 2 থেকে 4 এর মধ্যে সিপিইউ কোরগুলি দ্বিগুণ করা সম্ভবত লিনাক্স বাক্সের গতি প্রায় দ্বিগুণ করবে, তবে 16 থেকে 32 এ দ্বিগুণ করা সম্ভবত বেশিরভাগ কাজের চাপের সাথে নয়।
একটি স্পিন লক হয় যখন কোনও প্রক্রিয়া নিয়মিতভাবে লকটি সরানোর জন্য পোল করে। এটি খারাপ হিসাবে বিবেচিত হয় কারণ প্রক্রিয়াটি অযথা চক্র (সাধারণত) গ্রাস করে। এটি লিনাক্স-নির্দিষ্ট নয়, তবে একটি সাধারণ প্রোগ্রামিং প্যাটার্ন। এবং যদিও এটি সাধারণত একটি খারাপ অনুশীলন হিসাবে বিবেচিত হয়, এটি আসলে সঠিক সমাধান; এমন অনেক ক্ষেত্রে রয়েছে যে স্পিনলক স্থায়ী হবে বলে আশা করা কয়েকটি চক্রের ব্যয়ের চেয়ে শিডিয়ুলার ব্যবহারের ব্যয় বেশি (সিপিইউ চক্রের ক্ষেত্রে) বেশি।
একটি স্পিনলকের উদাহরণ:
#!/bin/sh
#wait for some program to clear a lock before doing stuff
while [ -f /var/run/example.lock ]; do
sleep 1
done
#do stuff
ঘন ঘন একটি স্পিন লক এড়ানোর উপায় আছে। এই নির্দিষ্ট উদাহরণের জন্য, ইনোটিফয়েট নামে একটি লিনাক্স সরঞ্জাম রয়েছে (এটি সাধারণত ডিফল্টরূপে ইনস্টল হয় না)। যদি এটি সি তে লেখা থাকে তবে আপনি কেবল লিনাক্স সরবরাহ করে এমন ইনোটাইফাই এপিআই ব্যবহার করবেন ।
একই উদাহরণ, ইনোটিফয়েট ব্যবহার করে কীভাবে স্পিন লক ছাড়াই একই জিনিস সম্পাদন করা যায় তা দেখায়:
#/bin/sh
inotifywait -e delete_self /var/run/example.lock
#do stuff
যখন কোনও থ্রেড একটি লক অর্জন করার চেষ্টা করে, তিনটি জিনিস ব্যর্থ হলে এটি ঘটতে পারে, এটি চেষ্টা করে এবং অবরুদ্ধ করতে পারে, এটি চেষ্টা করতে এবং চালিয়ে যেতে পারে, এটি চেষ্টা করতে পারে যখন কোনও ঘটনা ঘটে তখন ওএসকে এটিকে জাগ্রত করতে বলে ঘুমাতে যেতে পারে।
এখন একটি চেষ্টা এবং চালিয়ে যাওয়া খুব কম সময় ব্যবহার করে তারপরে চেষ্টা করুন এবং অবরুদ্ধ করুন। এই মুহুর্তের জন্য বলি যে "চেষ্টা করুন এবং চালিয়ে যান" আমার একক সময় লাগবে এবং "চেষ্টা ও ব্লক" নিতে একশত সময় লাগবে।
এখন আমাদের এই মুহুর্তের জন্য ধরে নেওয়া যাক যে লকটি ধরে রাখার জন্য গড়ে একটি থ্রেড সময় নিতে 4 ইউনিট সময় নেবে। 100 ইউনিট অপেক্ষা করা অপব্যয়কর। সুতরাং পরিবর্তে আপনি "চেষ্টা করুন এবং অবিরত করুন" এর একটি লুপ লিখুন। আগাম প্রচেষ্টায় আপনি সাধারণত লকটি অর্জন করবেন। এটি একটি স্পিন লক। এটিকে বলা হয়ে থাকে কারণ এটি লক না পাওয়া পর্যন্ত থ্রেডটি স্পিনিং করে রাখে।
একটি অতিরিক্ত সুরক্ষা পরিমাপ হ'ল লুপটি কতবার চালায় তা সীমাবদ্ধ করে। সুতরাং উদাহরণস্বরূপ আপনি লুপ রানের জন্য উদাহরণ তৈরি করেন যেমন ছয়বার, যদি এটি ব্যর্থ হয় তবে আপনি "চেষ্টা করুন এবং অবরুদ্ধ করুন"।
যদি আপনি জানেন যে একটি থ্রেড সর্বদা 200 ইউনিট বলার জন্য লকটি ধরে রাখে, তবে আপনি প্রতিটি চেষ্টা করে চালিয়ে যাওয়ার জন্য কম্পিউটারের সময় নষ্ট করছেন।
সুতরাং শেষ পর্যন্ত, একটি স্পিন লক খুব দক্ষ বা অপব্যয়কর হতে পারে। যখন লকটি ধরার জন্য "সাধারণ" সময় বেশি হয় তখন এটি অপব্যয় হয় তবে "চেষ্টা করে অবরুদ্ধ করতে" সময় লাগে। এটি কার্যকর যখন লকটি ধরে রাখার সাধারণ সময়টি অনেক কম হয় তখন 'চেষ্টা করে অবরুদ্ধ করার' সময়।
PS: থ্রেডগুলিতে পড়ার বইটি "একটি থ্রেড প্রাইমার", যদি আপনি এখনও এটি খুঁজে পেতে পারেন।
একটি লক দুটি বা আরও বেশি কাজের (প্রক্রিয়া, থ্রেড) সিঙ্ক্রোনাইজ করার একটি উপায়। বিশেষত, যখন উভয় কাজগুলির জন্য এক সময় কেবলমাত্র একটি কাজ দ্বারা ব্যবহৃত একটি সংস্থার মধ্যে অন্তর্বর্তী অ্যাক্সেসের প্রয়োজন হয়, কার্যগুলি একই সাথে সংস্থানটি ব্যবহার না করার ব্যবস্থা করার উপায়। সংস্থানটি অ্যাক্সেস করার জন্য, একটি কার্য অবশ্যই নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করবে:
take the lock
use the resource
release the lock
যদি অন্য কোনও কাজ ইতিমধ্যে গ্রহণ করে থাকে তবে লক নেওয়া সম্ভব নয়। (লকটিকে দৈহিক টোকেন অবজেক্ট হিসাবে মনে করুন ither হয় বস্তুটি একটি ড্রয়ারে রয়েছে, বা কারও হাতে রয়েছে Only কেবলমাত্র সেই বস্তুটি ধারণ করা ব্যক্তিই সেই সংস্থানটি অ্যাক্সেস করতে পারে)) সুতরাং "লকটি নেওয়া" এর অর্থ "অপেক্ষা করা অবধি অপেক্ষা করুন" আর কারও কাছে তালা নেই, তবে এটি নিয়ে যাও ”।
উচ্চ-স্তরের দৃষ্টিকোণ থেকে, লকগুলি কার্যকর করার জন্য দুটি প্রধান উপায় রয়েছে: স্পিনলকস এবং শর্তাদি। সঙ্গে spinlocks , Noone পর্যন্ত শুধু "ঘূর্ণায়মান" (অর্থাত একটি লুপ অসম্মতির) লক উপায়ে গ্রহণ আর লক হয়েছে। শর্তগুলির সাথে, যদি কোনও কাজ লকটি ধরার চেষ্টা করে তবে অন্য কোনও কাজ এটি ধারণ করে কারণ অবরুদ্ধ করে দেওয়া হয়, নতুন আগত একটি অপেক্ষার সারিতে প্রবেশ করে; রিলিজ অপারেশনটি যে কোনও ওয়েটিং টাস্কের সংকেত দেয় যে লকটি এখন উপলব্ধ।
(এই ব্যাখ্যাগুলি আপনাকে একটি লক বাস্তবায়নের পক্ষে যথেষ্ট নয়, কারণ আমি পারমাণবিকতা সম্পর্কে কিছু বলিনি But তবে এখানে পারমাণবিকতা গুরুত্বপূর্ণ নয়))
স্পিনলকগুলি স্পষ্টতই অপব্যয়যুক্ত: অপেক্ষার কাজটি লকটি নেওয়া হয়েছে কিনা তা পরীক্ষা করে রাখে। তাহলে এটি কখন এবং কখন ব্যবহৃত হয়? লকটি রাখা হয়নি এমন ক্ষেত্রে স্পিনলকগুলি প্রায়শই পাওয়া খুব সস্তা। লকটি রাখার সুযোগ যখন কম থাকে তখন এটি আকর্ষণীয় করে তোলে। তদ্ব্যতীত, স্পিনলকগুলি কেবলমাত্র তখনই কার্যকর হয় যদি লকটি পেতে বেশি সময় লাগে না। সুতরাং স্পিনলকগুলি এমন পরিস্থিতিতে ব্যবহার করা হয় যেখানে তারা খুব অল্প সময়ের জন্য অধিষ্ঠিত থাকবে, যাতে বেশিরভাগ প্রচেষ্টা প্রথম চেষ্টাতেই সফল হবে বলে আশা করা হয় এবং যাদের অপেক্ষা অপেক্ষা করা হয় তারা বেশিক্ষণ অপেক্ষা করেন না।
লিনাক্স ডিভাইস ড্রাইভারদের লিনাক্স কার্নেলের স্পিনলকস এবং অন্যান্য সম্মতি পদ্ধতির একটি ভাল ব্যাখ্যা রয়েছে , অধ্যায় 5।
synchronized
একটি স্পিনলক দ্বারা বাস্তবায়িত হবে: একটি synchronized
ব্লক খুব দীর্ঘ সময়ের জন্য চলতে পারে। synchronized
কিছু ক্ষেত্রে লকগুলি সহজেই ব্যবহার করা সহজতর করার জন্য একটি ভাষা নির্মাণ, বৃহত্তর সিঙ্ক্রোনাইজেশন আদিম তৈরির জন্য আদিম নয়।
একটি স্পিনলক হ'ল একটি লক যা শিডিয়ুলার অক্ষম করে এবং সম্ভবত সেই নির্দিষ্ট কোরটিতে বাধা হয়ে থাকে (ইরকস্যাভ বৈকল্পিক) যেটি লকটি অর্জিত হয়। এটি কোনও মিটেক্সের থেকে পৃথক যে এটি শিডিয়ুলিং অক্ষম করে তাই স্পিনলক ধরার সময় কেবল আপনার থ্রেড চলতে পারে। একটি মুটেক্স অন্যান্য উচ্চ অগ্রাধিকারের থ্রেডগুলি রাখা হওয়ার সময় নির্ধারিত করার অনুমতি দেয় তবে সেগুলি একই সাথে সুরক্ষিত বিভাগটি কার্যকর করতে দেয় না। স্পিনলকগুলি মাল্টিটাস্কিং অক্ষম করে কারণ আপনি একটি স্পিনলক নিতে পারবেন না এবং তারপরে অন্য কোনও কোড কল করুন যা একটি মুটেক্স অর্জন করার চেষ্টা করবে। স্পিনলক বিভাগের অভ্যন্তরে আপনার কোডটি কখনই ঘুমায় না (কোডটি সাধারণত যখন ঘুমায় তখন লক মুকেক্স বা খালি সেমফোরের মুখোমুখি হয়)।
মিউটেক্সের সাথে আরেকটি পার্থক্য হ'ল থ্রেডগুলি সাধারণত একটি মুটেক্সের জন্য সারি করে তাই নীচে একটি মিউেক্সের একটি সারি থাকে। স্পিনলক কেবল নিশ্চিত করে যে অন্য কোনও থ্রেড চালানোর পরেও চলবে না। অতএব, আপনার ফাইলের বাইরে ফাংশনগুলি কল করার সময় আপনাকে কখনই স্পিনলক ধরতে হবে না যে আপনি নিশ্চিত নন যে ঘুমবেন না।
আপনার স্পিনলকটি কোনও বাধা দিয়ে ভাগ করতে চাইলে আপনাকে অবশ্যই ইরক্যাসেভ বৈকল্পিকটি ব্যবহার করতে হবে। এটি কেবল শিডিয়ুলার অক্ষম করবে না তবে বাধাও অক্ষম করবে। এটা বোধগম্য করে তোলে? স্পিনলক কাজটি নিশ্চিত করে কাজ করে যাতে অন্য কিছু চলবে না। আপনি যদি কোনও বাধা দৌড়াতে না চান তবে আপনি এটি অক্ষম করুন এবং নিরাপদে সমালোচনামূলক বিভাগে যান।
মাল্টিকোর মেশিনে একটি স্পিনলক প্রকৃতপক্ষে অন্য একটি কোরের জন্য অপেক্ষা করত যা এটি ছেড়ে দেওয়ার জন্য লকটি ধারণ করে। এই স্পিনিংটি কেবল মাল্টিকোর মেশিনেই ঘটে কারণ একক কোরগুলিতে এটি ঘটতে পারে না (আপনি হয় স্পিনলক ধরে রেখে এগিয়ে যান অথবা লকটি প্রকাশ না হওয়া পর্যন্ত আপনি কখনই চালাবেন না)।
স্পিনলক অপ্রয়োজনীয় যেখানে এটি উপলব্ধি করে না। খুব ছোট সমালোচনামূলক বিভাগগুলির জন্য গুরুত্বপূর্ণ কাজ শেষ করার জন্য কয়েকটি মাইক্রোসেকেন্ডের জন্য শিডিয়ুলারকে কেবল স্থগিতকরণের তুলনায় একটি মুটেক্স টাস্ক সারি বরাদ্দ করা ব্যর্থ হবে। আইও অপারেশন জুড়ে আপনার যদি ঘুমের প্রয়োজন বা লকটি ধরে রাখা দরকার (যা ঘুমিয়ে থাকতে পারে) তবে একটি মিউটেক্স ব্যবহার করুন। অবশ্যই কোনও স্পিনলককে কখনই লক করবেন না এবং তারপরে এটি একটি বিঘ্নের মধ্যে ছেড়ে দেওয়ার চেষ্টা করবেন না। এটি যখন কাজ করবে তখন এটি আরডুইনো ক্রেপের মতো হবে (ফ্ল্যাগনোটসেট); এই ক্ষেত্রে একটি semaphore ব্যবহার করুন।
মেমরি লেনদেনের ব্লকগুলির জন্য যখন আপনাকে সাধারণ পারস্পরিক বর্জনীয় প্রয়োজন তখন একটি স্পিনলক ধরুন। যখন আপনি একাধিক থ্রেড ডান থামাতে চান তখন একটি মুটেক্সটি ধরুন এবং তারপরে মুখ্যেক্স মুক্ত হয়ে যাওয়ার পরে সর্বোচ্চ অগ্রাধিকারের থ্রেডটি বেছে নেওয়া বেছে নেওয়া হবে এবং যখন আপনি একই থ্রেডে লক করে ছেড়ে দেবেন। যখন আপনি এটি একটি থ্রেড বা একটি বাধাগুলি পোস্ট করতে এবং অন্য থ্রেডে নেওয়ার পরিকল্পনা করেন তখন একটি সেমফোরটি ধরুন। পারস্পরিক বর্জন নিশ্চিত করার জন্য এটি তিনটি ভিন্ন ভিন্ন উপায় এবং সেগুলি সামান্য ভিন্ন উদ্দেশ্যে ব্যবহৃত হয়।