বনাম লক নিরীক্ষণ


90

সি # তে থ্রেড সুরক্ষার জন্য Monitorক্লাস বা lockকীওয়ার্ডটি ব্যবহার করা কখন উপযুক্ত ?

সম্পাদনা: উত্তরগুলি থেকে এখন পর্যন্ত মনে lockহচ্ছে এটি Monitorক্লাসে কয়েকটি কলের জন্য সংক্ষিপ্ত হাত । লক কলটি শর্ট-হ্যান্ডের জন্য ঠিক কী? বা আরও স্পষ্টভাবে,

class LockVsMonitor
{
    private readonly object LockObject = new object();
    public void DoThreadSafeSomethingWithLock(Action action)
    {
        lock (LockObject)
        {
            action.Invoke();
        }
    }
    public void DoThreadSafeSomethingWithMonitor(Action action)
    {
        // What goes here ?
    }
}

হালনাগাদ

আপনার সহায়তার জন্য সবাইকে ধন্যবাদ: আপনার দেওয়া সমস্ত তথ্যের কিছু অনুসরণ করার জন্য আমি একটি আর একটি প্রশ্ন পোস্ট করেছি। যেহেতু আপনি এই ক্ষেত্রটি সম্পর্কে ভাল পারদর্শী বলে মনে হচ্ছে, আমি লিঙ্কটি পোস্ট করেছি: লক করা ব্যতিক্রমগুলি লক করা এবং পরিচালনা করার ক্ষেত্রে এই সমাধানটিতে কী ভুল?

উত্তর:


90

এরিক লিপার্ট তার ব্লগে এই সম্পর্কে কথা বলেছেন: লক্স এবং ব্যতিক্রমগুলি মিশে না

সমতুল্য কোড সি # 4.0 এবং পূর্ববর্তী সংস্করণগুলির মধ্যে পৃথক।


সি # 4.0 এ এটি:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    { body }
}
finally
{
    if (lockWasTaken) Monitor.Exit(temp);
}

Monitor.Enterলকটি যখন নেওয়া হয় তখন এটি পতাকাটিকে পরমাণুভাবে স্থাপনের উপর নির্ভর করে ।


এবং এর আগে এটি ছিল:

var temp = obj;
Monitor.Enter(temp);
try
{
   body
}
finally
{
    Monitor.Exit(temp);
}

এটি Monitor.Enterএবং এর মধ্যে নিক্ষিপ্ত কোন ব্যতিক্রমের উপর নির্ভর করে try। আমি মনে করি ডিবাগ কোডে এই শর্তটি লঙ্ঘিত হয়েছিল কারণ সংকলক তাদের মধ্যে একটি এনওপি andুকিয়েছে এবং এইভাবে সম্ভবগুলির মধ্যে থ্রেড গর্ভপাত তৈরি করেছে।


যেমনটি আমি বলেছি প্রথম উদাহরণটি সি # 4 এবং অন্যটি পূর্ববর্তী সংস্করণগুলি ব্যবহার করে।
কোডসইনচাউস

পার্শ্ব নোট হিসাবে, সি # এর মাধ্যমে সি # তে লক কীওয়ার্ডের একটি সতর্কতার কথা উল্লেখ করা হয়েছে: আপনি প্রায়শই লকটি ছাড়ার আগে দুর্নীতিগ্রস্থ অবস্থা পুনরুদ্ধার করতে কিছু করতে চাইবেন (যদি প্রযোজ্য হয়)। যেহেতু লক কীওয়ার্ডটি জিনিসগুলিকে ক্যাচ ব্লকে রাখে না, তাই আমাদের তুচ্ছ রুটিনের জন্য অবশেষে দীর্ঘ সংস্করণ লেখার চেষ্টা করা উচিত।
kizzx2

4
আইএমও ভাগ করা রাষ্ট্রটি পুনরুদ্ধার করা লকিং / মাল্টি-থ্রেডিংয়ের সংলগ্ন। সুতরাং এটি চেষ্টা / শেষ অবধি lockব্লকের ভিতরে দিয়ে করা উচিত ।
কোডসইনচাউস

4
@ কিজএক্সএক্স 2: পাঠক-লেখকের লকগুলির সাথে এই জাতীয় প্যাটার্নটি বিশেষত দুর্দান্ত লাগবে। যদি কোনও পাঠক লক ধারণ করে এমন কোডের মধ্যে কোনও ব্যতিক্রম ঘটে তবে রক্ষিত সংস্থানটি ক্ষতিগ্রস্থ হতে পারে এমন আশা করার কোনও কারণ নেই এবং সুতরাং এটি অকার্যকর করার কোনও কারণ নেই। যদি কোনও লেখক লকের মধ্যে কোনও ব্যতিক্রম ঘটে এবং ব্যতিক্রম-হ্যান্ডলিং কোডটি স্পষ্টভাবে নির্দেশ করে না যে রক্ষিত বস্তুর রাজ্যটি মেরামত করা হয়েছে, তবে এটি নির্দেশ করবে যে অবজেক্টটি ক্ষতিগ্রস্থ হতে পারে এবং অবৈধ হওয়া উচিত। আইএমএইচও, অপ্রত্যাশিত ব্যতিক্রমগুলির কোনও প্রোগ্রাম ক্রাশ হওয়া উচিত নয়, তবে এটি দুর্নীতিগ্রস্থ হতে পারে এমন কোনও কিছুকে অকার্যকর করতে হবে।
সুপারক্যাট

4
@ আরসেনজাহারে @ আপনার Pulseজন্য সহজ লকিংয়ের দরকার নেই এটি কয়েকটি উন্নত মাল্টি-থ্রেডিং পরিস্থিতিতে গুরুত্বপূর্ণ। আমি কখনও Pulseসরাসরি ব্যবহার করি নি ।
কোডসইনচাওস

43

lock+ এবং এর Monitor.Enterসাথে কেবল শর্টকাট । যখনই এটি পর্যাপ্ত হয় লক স্টেটমেন্টটি ব্যবহার করুন - আপনার যদি ট্রাইএনটারের মতো কিছু প্রয়োজন হয় তবে আপনাকে মনিটর ব্যবহার করতে হবে।tryfinallyMonitor.Exit


23

একটি লক স্টেটমেন্ট এর সমতুল্য:

Monitor.Enter(object);
try
{
   // Your code here...
}
finally
{
   Monitor.Exit(object);
}

তবে, মনে রাখবেন যে মনিটরও () এবং পালস () অপেক্ষা করতে পারে যা জটিল মাল্টিথ্রেডিং পরিস্থিতিতে প্রায়শই দরকারী।

হালনাগাদ

তবে সি # 4 এ এটি ভিন্নভাবে প্রয়োগ করা হয়েছে:

bool lockWasTaken = false;
var temp = obj;
try 
{
     Monitor.Enter(temp, ref lockWasTaken); 
     //your code
}
finally 
{ 
     if (lockWasTaken) 
             Monitor.Exit(temp); 
} 

মন্তব্য এবং লিঙ্কগুলির জন্য থ্যাঙ্কস থেকে কোডআইএনচাউস


সি # 4 এ লক স্টেটমেন্টটি ভিন্নভাবে প্রয়োগ করা হয়। ব্লগস.এমএসডিএন
বি /

16

Monitorআরও নমনীয়। মনিটর ব্যবহারের আমার প্রিয় ব্যবহারের ক্ষেত্রেটি হল আপনি যখন নিজের পালাটির জন্য অপেক্ষা করতে চান না এবং কেবল এড়িয়ে যান :

//already executing? forget it, lets move on
if(Monitor.TryEnter(_lockObject))
{
    //do stuff;
    Monitor.Exit(_lockObject);
}

6

অন্যরা lockযেমন বলেছে, এর সাথে "সমতুল্য"

Monitor.Enter(object);
try
{
   // Your code here...
}
finally
{
   Monitor.Exit(object);
}

তবে কৌতূহলের বাইরে lockআপনি যে রেফারেন্সটি পাঠিয়েছেন সেটি সংরক্ষণ করবে এবং আপনি যদি এটি পরিবর্তন করেন তবে ফেলে দেবেন না।আমি জানি এটি লক করা অবজেক্টটি পরিবর্তন করার প্রস্তাব দেওয়া হয়নি এবং আপনি এটি করতে চান না।

তবে আবার বিজ্ঞানের পক্ষে এটি কাজ করে:

var lockObject = "";
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
    tasks.Add(Task.Run(() =>
    {
        Thread.Sleep(250);
        lock (lockObject)
        {
            lockObject += "x";
        }
    }));
Task.WaitAll(tasks.ToArray());

... এবং এটি করে না:

var lockObject = "";
var tasks = new List<Task>();
for (var i = 0; i < 10; i++)
    tasks.Add(Task.Run(() =>
    {
        Thread.Sleep(250);
        Monitor.Enter(lockObject);
        try
        {
            lockObject += "x";
        }
        finally
        {
            Monitor.Exit(lockObject);
        }
    }));
Task.WaitAll(tasks.ToArray());

ত্রুটি:

'সিস্টেম.Treadread.SynchronizationLockException' টাইপের একটি ব্যতিক্রম 70783 এসটিউডিইএস.ইক্সিতে ঘটেছিল তবে ব্যবহারকারী কোডে পরিচালিত হয়নি type

অতিরিক্ত তথ্য: অবজেক্ট সিঙ্ক্রোনাইজেশন পদ্ধতিটি কোডের একটি সিঙ্কক্রোনাইজ করা ব্লক থেকে কল করা হয়েছিল।

এটি হ'ল কারণ যা পরিবর্তিত হয়েছে Monitor.Exit(lockObject);তার উপর অভিনয় করবে lockObjectকারণ stringsঅপরিবর্তনীয়, তারপরে আপনি এটিকে কোডের একটি অযৌক্তিক ব্লক থেকে কল করছেন .. তবে যাই হোক। এটি কেবল একটি মজার সত্য is


"এটি কারণ মনিটর.এক্সিট (লকঅবজেক্ট); লকঅবজেক্টে কাজ করবে"। তারপরে লক কিছু না দিয়ে বস্তুটি? লক কীভাবে কাজ করে?
Yugo Amaryl

@ ইউগো অ্যামেরিল, আমি মনে করি এটি কারণ কারণ লক স্টেটমেন্টটি প্রথমে উত্তীর্ণ রেফারেন্সকে মনে রাখে এবং তারপরে পরিবর্তিত রেফারেন্সটি ব্যবহার না করে ব্যবহার করুন, যেমন:object temp = lockObject; Monitor.Enter(temp); <...locked code...> Monitor.Exit(temp);
ঝুরাভ্লেভ এ।

3

দুটোই একই জিনিস। লক সি তীক্ষ্ণ কীওয়ার্ড এবং মনিটরের ক্লাস ব্যবহার করুন।

http://msdn.microsoft.com/en-us/library/ms173179(v=vs.80).aspx


4
এ লুক msdn.microsoft.com/en-us/library/ms173179(v=vs.80).aspx "বস্তুত, লক শব্দ মনিটর বর্গ সঙ্গে বাস্তবায়িত হয় উদাহরণস্বরূপ।"
RobertoBr

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

3

লক এবং মনিটরের বেসিক আচরণ (প্রবেশ + প্রস্থান) কমবেশি একই রকম হয় তবে মনিটরে আরও বিকল্প রয়েছে যা আপনাকে আরও সুসংগতকরণের সম্ভাবনাগুলিকে অনুমতি দেয়।

লকটি একটি শর্টকাট এবং এটি প্রাথমিক ব্যবহারের বিকল্প option

আপনার যদি আরও নিয়ন্ত্রণের প্রয়োজন হয় তবে মনিটরটি আরও ভাল বিকল্প। উন্নত ব্যবহারের জন্য (যেমন বাধা, সেমোফোর এবং অন্যান্য) ওয়েট, ট্রাইএন্টার এবং পালস ব্যবহার করতে পারেন।


1

লক লক কীওয়ার্ডটি নিশ্চিত করে যে একটি থ্রেড এক সময় কোডের একটি অংশকে কার্যকর করছে।

লক (লকঅবজেক্ট)

        {
        //   Body
        }

লক কীওয়ার্ড একটি প্রদত্ত বস্তুর জন্য পারস্পরিক-বর্জনীয় লকটি প্রাপ্ত করে একটি বিবৃতি কার্যকর করে এবং তারপরে লকটি প্রকাশ করে একটি বিবৃতি ব্লককে একটি গুরুত্বপূর্ণ বিভাগ হিসাবে চিহ্নিত করে

যদি অন্য থ্রেড কোনও লকড কোড প্রবেশ করানোর চেষ্টা করে তবে অবজেক্টটি প্রকাশ না হওয়া পর্যন্ত এটি অপেক্ষা করবে, অবরুদ্ধ করবে।

মনিটর মনিটর একটি স্ট্যাটিক শ্রেণি এবং এটি সিস্টেমের সাথে সম্পর্কিত h নামকরণ স্থান।

এটি অবজেক্টটিতে একচেটিয়া লক সরবরাহ করে যাতে নির্দিষ্ট সময়টিতে শুধুমাত্র একটি থ্রেড সমালোচনামূলক বিভাগে প্রবেশ করতে পারে।

সি # তে মনিটর এবং লকের মধ্যে পার্থক্য

লকটি মনিটরের শর্টকাট। চেষ্টা করুন এবং শেষ পর্যন্ত প্রবেশ করুন। লক হ্যান্ডলগুলি চেষ্টা করুন এবং অবশেষে অভ্যন্তরীণভাবে ব্লক করুন লক = মনিটর + অবশেষে চেষ্টা করুন।

আপনি যদি আরও , এবং TryEnter() Wait(), উন্নত মাল্টিথ্রেডিং সমাধানগুলি প্রয়োগ করে আরও কার্যকর করতে চানPulse()PulseAll() পদ্ধতি, তারপর মনিটর বর্গ আপনার বিকল্প।

সি # Monitor.wait(): একটি থ্রেড অন্য থ্রেডকে অবহিত করার জন্য অপেক্ষা করে।

Monitor.pulse(): একটি থ্রেড অন্য থ্রেডকে অবহিত করে।

Monitor.pulseAll(): একটি থ্রেড একটি প্রক্রিয়ার মধ্যে অন্যান্য সমস্ত থ্রেডকে অবহিত করে


0

উপরের সমস্ত ব্যাখ্যা ছাড়াও, লকটি একটি সি # বিবৃতি যেখানে মনিটর সিস্টেমের মধ্যে অবস্থিত .NET এর একটি শ্রেণি h

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.