উত্তর:
Http://en.wikedia.org/wiki/Deadlock থেকে নেওয়া :
একযোগে কম্পিউটিংয়ে, একটি অচলাবস্থা এমন একটি অবস্থা যেখানে ক্রিয়াকলাপের একটি গ্রুপের প্রতিটি সদস্য কোনও অন্য সদস্যের একটি লক প্রকাশের অপেক্ষায় থাকে
একটি লাইভলক একটি অচলাবস্থার অনুরূপ, ব্যতীত লাইভলকের সাথে জড়িত প্রক্রিয়ার রাজ্যগুলি একে অপরের বিষয়ে ক্রমাগত পরিবর্তিত হয়, কোনওটিই অগ্রগতি করে না। লাইভলক সম্পদ অনাহার একটি বিশেষ ক্ষেত্রে; সাধারণ সংজ্ঞা কেবলমাত্র বলে যে একটি নির্দিষ্ট প্রক্রিয়া অগ্রগতি করছে না।
লাইভলকের একটি বাস্তব-জগতের উদাহরণটি দেখা যায় যখন দু'জন লোক সংকীর্ণ করিডোরে মিলিত হয় এবং প্রত্যেকে একে অপরকে যেতে দিতে একদিকে সরে গিয়ে বিনয়ী হওয়ার চেষ্টা করে, তবে তারা কোনও অগ্রগতি না করেই পাশ থেকে অন্যদিকে দুলতে থাকে কারণ তারা দু'বার বারবার সরে যায় move একই সময়ে একই সময়ে।
লাইভলোক হ'ল কিছু অ্যালগরিদমের সাথে ঝুঁকি যা সনাক্ত করে এবং অচলাবস্থা থেকে পুনরুদ্ধার করে। যদি একাধিক প্রক্রিয়া পদক্ষেপ নেয়, অচল সনাক্তকরণ অ্যালগরিদম বারবার ট্রিগার করা যেতে পারে। কেবলমাত্র একটি প্রক্রিয়া (এলোমেলোভাবে বা অগ্রাধিকার অনুসারে নির্বাচিত) পদক্ষেপ গ্রহণ করে তা নিশ্চিত করে এড়ানো যায়।
একটি থ্রেড প্রায়শই অন্য থ্রেডের ক্রিয়া প্রতিক্রিয়া হিসাবে কাজ করে। অন্য থ্রেডের ক্রিয়াটি যদি অন্য থ্রেডের ক্রিয়াটির প্রতিক্রিয়াও হয় তবে লাইভলকের ফলাফল হতে পারে।
অচলাবস্থার মতো, লাইভলকড থ্রেডগুলি আরও অগ্রগতি করতে অক্ষম । যাইহোক, থ্রেডগুলি অবরুদ্ধ করা হয়নি - তারা কাজটি আবার শুরু করতে একে অপরের সাড়া দিতে খুব ব্যস্ত । এটি দুটি করিডোরে একে অপরকে পাস করার চেষ্টা করার সাথে তুলনীয়: আলফোনস গ্যাস্টনকে যেতে দিতে তার বাম দিকে চলে যায়, এবং গ্যাস্টন আলফোনকে পাস করতে দিতে তার ডানদিকে চলে যায় moves তারা এখনও একে অপরকে অবরুদ্ধ করছে তা দেখে, আলফোনস তার ডানদিকে চলে যায়, এবং গ্যাস্টন তার বাম দিকে চলে যায়। তারা এখনও একে অপরকে অবরুদ্ধ করছে, এবং আরও অনেক কিছু ...
লাইভলক এবং অচলাবস্থার মধ্যে প্রধান পার্থক্য হ'ল থ্রেডগুলি ব্লক করা হচ্ছে না, পরিবর্তে তারা একে অপরকে অবিরত সাড়া দেওয়ার চেষ্টা করবে।
এই চিত্রটিতে, উভয় চেনাশোনা (থ্রেড বা প্রক্রিয়া) বাম এবং ডানদিকে সরানোর মাধ্যমে অপরটিকে স্থান দেওয়ার চেষ্টা করবে। তবে তারা আর কোনও পদক্ষেপ নিতে পারে না।
এখানে সমস্ত বিষয়বস্তু এবং উদাহরণ থেকে
অপারেটিং সিস্টেমগুলি: অভ্যন্তরীণ এবং ডিজাইনের নীতিগুলি
উইলিয়াম স্ট্যালিংস
8º সংস্করণ
অচলাবস্থা : এমন একটি পরিস্থিতিতে যেখানে দুই বা ততোধিক প্রক্রিয়া এগিয়ে যেতে অক্ষম হয় কারণ প্রত্যেকে একে অপরের জন্য কিছু করার জন্য অপেক্ষা করে।
উদাহরণস্বরূপ, দুটি প্রক্রিয়া, P1 এবং P2 এবং দুটি সংস্থান, আর 1 এবং আর 2 বিবেচনা করুন। ধরুন যে প্রতিটি প্রক্রিয়াটির ক্রিয়াকলাপের অংশটি সম্পাদনের জন্য উভয় সংস্থার অ্যাক্সেসের প্রয়োজন। তারপরে নিম্নলিখিত পরিস্থিতিটি পাওয়া সম্ভব: ওএস আর 1 কে পি 2, এবং আর 2 কে পি 1 প্রদান করে। প্রতিটি প্রক্রিয়া দুটি সংস্থার একটির জন্য অপেক্ষা করছে। অন্য সংস্থান অর্জন না করে এবং উভয় সংস্থার প্রয়োজনে ফাংশন সম্পাদন না করা পর্যন্ত এটি ইতিমধ্যে মালিকানাধীন সংস্থানটি প্রকাশ করবে না। দুটি প্রক্রিয়া অচল অবস্থায় রয়েছে
লাইভলক : এমন একটি পরিস্থিতিতে যেখানে দুটি বা আরও বেশি প্রক্রিয়া কোনও কার্যকর কাজ না করেই অন্য প্রক্রিয়া (এস) এর পরিবর্তনের প্রতিক্রিয়া হিসাবে তাদের রাজ্যগুলিকে অবিচ্ছিন্নভাবে পরিবর্তন করে:
অনাহার : একটি পরিস্থিতি যেখানে একটি চলমান প্রক্রিয়া তফসিলকারী দ্বারা অনির্দিষ্টকালের জন্য উপেক্ষা করা হয়; যদিও এটি এগিয়ে যেতে সক্ষম, এটি কখনই চয়ন করা হয় না।
ধরুন যে তিনটি প্রক্রিয়া (পি 1, পি 2, পি 3) প্রতিটি রিসোর্স আরের পর্যায়ক্রমিক অ্যাক্সেসের প্রয়োজন। P1 এবং P3 উভয়ই সেই সংস্থার জন্য অপেক্ষা করে এমন পরিস্থিতিতে বিবেচনা করুন। যখন পি 1 তার সমালোচনামূলক বিভাগটি থেকে বেরিয়ে আসে, তখন পি 2 বা পি 3 কে আর এর অ্যাক্সেসের অনুমতি দেওয়া উচিত ume অনুমান করুন যে ওএস পি 3 এর অ্যাক্সেস দেয় এবং পি 3 এর সমালোচনামূলক বিভাগটি সম্পূর্ণ করার আগে পি 1 আবার অ্যাক্সেসের প্রয়োজন। পি 3 শেষ হওয়ার পরে ওএস যদি পি 1 এ অ্যাক্সেস দেয় এবং পরবর্তী সময়ে পি 1 এবং পি 3 এ অ্যাক্সেস দেয় তবে পিড 2 অনির্দিষ্টকালের জন্য রিসোর্সে অ্যাক্সেস অস্বীকার করতে পারে, যদিও কোনও অচলাবস্থার পরিস্থিতি নেই।
পরিশিষ্ট এ - কনসার্নির বিষয়সমূহ
অচল উদাহরণ
উভয় প্রক্রিয়া যদি বিবৃতিটি কার্যকর করার আগে উভয় প্রক্রিয়াতে তাদের পতাকাগুলি সত্য করে দেয় তবে প্রতিটি একে অপরটি তার সমালোচনামূলক বিভাগে প্রবেশ করেছে, যার ফলে অচলাবস্থার সৃষ্টি হয় causing
/* PROCESS 0 */
flag[0] = true; // <- get lock 0
while (flag[1]) // <- is lock 1 free?
/* do nothing */; // <- no? so I wait 1 second, for example
// and test again.
// on more sophisticated setups we can ask
// to be woken when lock 1 is freed
/* critical section*/; // <- do what we need (this will never happen)
flag[0] = false; // <- releasing our lock
/* PROCESS 1 */
flag[1] = true;
while (flag[0])
/* do nothing */;
/* critical section*/;
flag[1] = false;
লাইভলক উদাহরণ
/* PROCESS 0 */
flag[0] = true; // <- get lock 0
while (flag[1]){
flag[0] = false; // <- instead of sleeping, we do useless work
// needed by the lock mechanism
/*delay */; // <- wait for a second
flag[0] = true; // <- and restart useless work again.
}
/*critical section*/; // <- do what we need (this will never happen)
flag[0] = false;
/* PROCESS 1 */
flag[1] = true;
while (flag[0]) {
flag[1] = false;
/*delay */;
flag[1] = true;
}
/* critical section*/;
flag[1] = false;
[...] ইভেন্টগুলির নিম্নলিখিত ক্রমটি বিবেচনা করুন:
এই ক্রমটি অনির্দিষ্টকালের জন্য বাড়ানো যেতে পারে এবং কোনও প্রক্রিয়াই তার সমালোচনামূলক বিভাগে প্রবেশ করতে পারে না। কড়া কথায় বলতে গেলে, এটি অচল নয় , কারণ দুটি প্রক্রিয়ার আপেক্ষিক গতিতে যে কোনও পরিবর্তন এই চক্রটি ভেঙে দেবে এবং কাউকে সমালোচনামূলক বিভাগে প্রবেশ করতে দেবে। এই অবস্থাটিকে লাইভলক হিসাবে উল্লেখ করা হয় । স্মরণ করুন যে অচলাবস্থা তখন ঘটে যখন প্রক্রিয়াগুলির একটি সেট তাদের সমালোচনামূলক বিভাগগুলিতে প্রবেশ করতে চায় তবে কোনও প্রক্রিয়া সফল হতে পারে না। সঙ্গে livelock সেখানে মৃত্যুদণ্ড কার্যকর করে সফল সম্ভাব্য ক্রম, কিন্তু এটি এক বা একাধিক সঞ্চালনের ক্রম যা কোন প্রক্রিয়া কি কখনো তার সমালোচনামূলক ধারা প্রবেশ বর্ণনা করা সম্ভব।
বই থেকে আর বিষয়বস্তু নয়।
আর স্পিনলকসের কী হবে?
স্পিনলক হ'ল ওএস লক ব্যবস্থার ব্যয় এড়াতে একটি কৌশল। সাধারণত আপনি করবেন:
try
{
lock = beginLock();
doSomething();
}
finally
{
endLock();
}
এর beginLock()
চেয়ে অনেক বেশি ব্যয় হলে একটি সমস্যা দেখা দিতে শুরু করে doSomething()
। খুব উত্সাহিত শর্তে, beginLock
1 সেকেন্ডের দাম পড়লে কী ঘটেছিল তা কল্পনা করুন , তবে doSomething
ব্যয় হয় মাত্র 1 মিলিসেকেন্ড।
এই ক্ষেত্রে যদি আপনি 1 মিলিসেকেন্ড অপেক্ষা করেন তবে আপনি 1 সেকেন্ডের জন্য বাধা দেওয়া এড়াতে পারবেন।
এত beginLock
খরচ হবে কেন ? লকটি নিখরচায় বিনামূল্যে ব্যয় না হলে ( https://stackoverflow.com/a/49712993/5397116 দেখুন ), তবে লকটি মুক্ত না হলে ওএস আপনার থ্রেডকে "হিমায়িত" করবে, আপনাকে জাগ্রত করার জন্য একটি ব্যবস্থা সেটআপ করুন যখন লকটি মুক্ত হয় এবং তারপরে আপনাকে ভবিষ্যতে আবার জাগিয়ে তুলবে।
এই সমস্ত কিছু লুপটি পরীক্ষা করে দেখার জন্য অনেক বেশি ব্যয়বহুল। যে কারণে কখনও কখনও একটি "স্পিনলক" করা ভাল।
উদাহরণ স্বরূপ:
void beginSpinLock(lock)
{
if(lock) loopFor(1 milliseconds);
else
{
lock = true;
return;
}
if(lock) loopFor(2 milliseconds);
else
{
lock = true;
return;
}
// important is that the part above never
// cause the thread to sleep.
// It is "burning" the time slice of this thread.
// Hopefully for good.
// some implementations fallback to OS lock mechanism
// after a few tries
if(lock) return beginLock(lock);
else
{
lock = true;
return;
}
}
যদি আপনার প্রয়োগটি সাবধান না হয় তবে আপনি লক মেকানিজমে সমস্ত সিপিইউ ব্যয় করে লাইভলকের উপর পড়তে পারেন।
আরও দেখুন:
https://preshing.com/20120226/roll-your-own-lightweight-mutex/
আমার স্পিন লক বাস্তবায়ন কি সঠিক এবং সর্বোত্তম?
সংক্ষিপ্তসার :
অচলাবস্থা : এমন পরিস্থিতি যেখানে কেউ অগ্রসর হয় না, কিছুই করে না (ঘুমানো, অপেক্ষারত ইত্যাদি ..)। সিপিইউ ব্যবহার কম হবে;
লাইভলক : এমন পরিস্থিতি যেখানে কেউ অগ্রসর হয় না, তবে সিপিইউ লক প্রক্রিয়াতে ব্যয় হয় আপনার গণনায় নয়;
অনাহার: এমন এক পরিস্থিতিতে যেখানে একজন প্রার্থী কখনই দৌড়ানোর সুযোগ পায় না; খাঁটি দুর্ভাগ্য দ্বারা বা এর কিছু সম্পত্তি দ্বারা (নিম্ন অগ্রাধিকার, উদাহরণস্বরূপ);
স্পিনলক : লকটি মুক্ত হওয়ার জন্য অপেক্ষা করা ব্যয়টি এড়ানোর কৌশল।
ডিএডলক ড্যাডলক এমন একটি শর্ত যেখানে কোনও কাজ অনির্দিষ্টকালের জন্য অপেক্ষা করে এমন শর্ত যা কখনই সন্তুষ্ট হতে পারে না - টাস্ক শেয়ারড রিসোর্সগুলির উপর একচেটিয়া নিয়ন্ত্রণ দাবি করে - টাস্ক রিসোর্সগুলিকে ধরে রাখে অন্য সংস্থানগুলি প্রকাশের অপেক্ষায় - কার্যগুলি সংস্থানগুলিকে আলাদা করতে বাধ্য করা যায় না - একটি বিজ্ঞপ্তি অপেক্ষা শর্ত বিদ্যমান
লাইভলক লাইভলক অবস্থা দেখা দিতে পারে যখন দুটি বা ততোধিক কাজ নির্ভর করে যখন কোনও বৃত্তাকার নির্ভরতা শর্ত সৃষ্টি করে এমন কিছু সংস্থান ব্যবহার করে যেখানে সেই কাজগুলি চিরকালের জন্য চলতে থাকে, এইভাবে নিম্ন স্তরের সমস্ত স্তরের কাজগুলি চলমান থেকে অবরুদ্ধ করে থাকে (এই নিম্ন অগ্রাধিকারের কাজগুলি অনাহার নামে পরিচিত)
সম্ভবত এই দুটি উদাহরণ আপনাকে অচলাবস্থা এবং লাইভলকের মধ্যে পার্থক্য তুলে ধরে:
অচলাবস্থার জন্য জাভা-উদাহরণ:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DeadlockSample {
private static final Lock lock1 = new ReentrantLock(true);
private static final Lock lock2 = new ReentrantLock(true);
public static void main(String[] args) {
Thread threadA = new Thread(DeadlockSample::doA,"Thread A");
Thread threadB = new Thread(DeadlockSample::doB,"Thread B");
threadA.start();
threadB.start();
}
public static void doA() {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
lock1.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
lock2.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doA()");
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
}
public static void doB() {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
lock2.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
lock1.lock();
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doB()");
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
}
}
নমুনা আউটপুট:
Thread A : waits for lock 1
Thread B : waits for lock 2
Thread A : holds lock 1
Thread B : holds lock 2
Thread B : waits for lock 1
Thread A : waits for lock 2
লাইভলকের জাভা-উদাহরণ:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LivelockSample {
private static final Lock lock1 = new ReentrantLock(true);
private static final Lock lock2 = new ReentrantLock(true);
public static void main(String[] args) {
Thread threadA = new Thread(LivelockSample::doA, "Thread A");
Thread threadB = new Thread(LivelockSample::doB, "Thread B");
threadA.start();
threadB.start();
}
public static void doA() {
try {
while (!lock1.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
while (!lock2.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doA()");
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
} catch (InterruptedException e) {
// can be ignored here for this sample
}
}
public static void doB() {
try {
while (!lock2.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 2");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 2");
try {
while (!lock1.tryLock()) {
System.out.println(Thread.currentThread().getName() + " : waits for lock 1");
Thread.sleep(100);
}
System.out.println(Thread.currentThread().getName() + " : holds lock 1");
try {
System.out.println(Thread.currentThread().getName() + " : critical section of doB()");
} finally {
lock1.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 1 any longer");
}
} finally {
lock2.unlock();
System.out.println(Thread.currentThread().getName() + " : does not hold lock 2 any longer");
}
} catch (InterruptedException e) {
// can be ignored here for this sample
}
}
}
নমুনা আউটপুট:
Thread B : holds lock 2
Thread A : holds lock 1
Thread A : waits for lock 2
Thread B : waits for lock 1
Thread B : waits for lock 1
Thread A : waits for lock 2
Thread A : waits for lock 2
Thread B : waits for lock 1
Thread B : waits for lock 1
Thread A : waits for lock 2
Thread A : waits for lock 2
Thread B : waits for lock 1
...
উভয় উদাহরণই থ্রেডগুলিকে বিভিন্ন অর্ডারগুলিতে লকগুলি অর্জন করতে বাধ্য করে। অচলাবস্থায় অন্য লকের জন্য অপেক্ষা করার সময়, লাইভলকটি সত্যিই অপেক্ষা করে না - এটি লকটি পাওয়ার সম্ভাবনা ছাড়াই জরুরীভাবে চেষ্টা করে। প্রতিটি চেষ্টা সিপিইউ চক্র গ্রহণ করে।
আপনি থ্রেড এ এবং থ্রেড বি কল্পনা করুন যে তারা উভয় synchronised
একই বস্তুতে রয়েছে এবং এই ব্লকের ভিতরে একটি বৈশ্বিক পরিবর্তনশীল রয়েছে যা তারা উভয়ই আপডেট করছে;
static boolean commonVar = false;
Object lock = new Object;
...
void threadAMethod(){
...
while(commonVar == false){
synchornized(lock){
...
commonVar = true
}
}
}
void threadBMethod(){
...
while(commonVar == true){
synchornized(lock){
...
commonVar = false
}
}
}
সুতরাং যখন থ্রেড 'এ প্রবেশ while
লুপ এবং লক ঝুলিতে, এটা আছে এটা করতে এবং সেট করতে হয়েছে কি commonVar
করতে true
। তারপর থ্রেড বি, আসে ঢোকে while
লুপ এবং যেহেতু commonVar
হয় true
এখন, এটা লক রাখা পাবে হয়। এটি তাই করে, synchronised
ব্লকটি কার্যকর করে এবং এতে commonVar
ফিরে আসে false
। এখন, থ্রেড একটি আবার নতুন CPU- র জানালা পায়, এটা ছিল প্রস্থান করার জন্য সম্পর্কে while
লুপ কিন্তু থ্রেড বি শুধু এটা ফিরে সেট করেছে false
, তাই চক্র পুনরাবৃত্তি আবার। থ্রেডগুলি কিছু করে (যাতে এগুলি প্রচলিত অর্থে অবরুদ্ধ করা হয় না) তবে প্রায় কিছুই না।
লাইভলকের অগত্যা এখানে উপস্থিত হওয়ার দরকার নেই বলে উল্লেখ করে এটিও দুর্দান্ত লাগবে। আমি ধরে নিচ্ছি যে synchronised
ব্লক ফিনিসটি এক্সিকিউট করার পরে শিডিয়ুলার অন্য থ্রেডের পক্ষে । বেশিরভাগ সময়, আমি মনে করি এটি হার্ড-হিট প্রত্যাশা এবং হুডের নীচে ঘটে যাওয়া অনেকগুলি বিষয়ের উপর নির্ভর করে।