আমি কেন একটি মিটেক্স লক করা আছে তা পরীক্ষা করতে পারছি না?


28

C ++ 14 মনে হচ্ছে কোনও std::mutexলক হয়েছে কিনা তা যাচাই করার জন্য একটি প্রক্রিয়া বাদ দিয়েছে । এই তাই প্রশ্ন দেখুন:

https://stackoverflow.com/questions/21892934/how-to-assert-if-a-stdmutex-is-locked

এর চারপাশে বেশ কয়েকটি উপায় রয়েছে, যেমন ব্যবহার করে;

std::mutex::try_lock()
std::unique_lock::owns_lock()

তবে এগুলির কোনওটিই বিশেষ সন্তোষজনক সমাধান নয়।

try_lock()একটি মিথ্যা নেতিবাচক ফেরত দেওয়ার অনুমতি দেওয়া হয়েছে এবং বর্তমান থ্রেডটি মিউটেক্সকে লক করে রাখলে তার অপরিবর্তিত আচরণ রয়েছে। এর পার্শ্ব-প্রতিক্রিয়াও রয়েছে। মূলটির উপরে owns_lock()একটি নির্মাণ প্রয়োজন ।unique_lockstd::mutex

স্পষ্টতই আমি আমার নিজস্ব রোল করতে পারি, তবে আমি বরং বর্তমান ইন্টারফেসের প্রেরণাগুলি বুঝতে পারি।

মিউটেক্সের অবস্থান পরীক্ষা করার ক্ষমতা (যেমন std::mutex::is_locked()) আমার কাছে কোনও রহস্যজনক অনুরোধ বলে মনে হয় না, তাই আমি সন্দেহ করি যে স্ট্যান্ডার্ড কমিটি পর্যবেক্ষণ হওয়ার চেয়ে এই বৈশিষ্ট্যটি ইচ্ছাকৃতভাবে বাদ দিয়েছে।

কেন?

সম্পাদনা: ঠিক আছে তাই সম্ভবত এই ব্যবহারের ক্ষেত্রে আমার প্রত্যাশার মতো সাধারণ পরিস্থিতি নেই, তাই আমি আমার নির্দিষ্ট দৃশ্যের চিত্র তুলে ধরব। আমার কাছে একটি মেশিন লার্নিং অ্যালগরিদম রয়েছে যা একাধিক থ্রেডে বিতরণ করা হয়। প্রতিটি থ্রেড অবিচ্ছিন্নভাবে পরিচালনা করে এবং একটি অনুকূলকরণের সমস্যাটি শেষ হয়ে গেলে একটি মাস্টার পুলে ফিরে আসে।

এটি তখন একটি মাস্টার মিটেক্স লক করে ks থ্রেডটি অবশ্যই একটি নতুন পিতামাতাকে বেছে নিতে হবে যা থেকে কোনও সন্তানের রূপান্তর করতে পারে তবে কেবলমাত্র এমন পিতামাতাদের কাছ থেকে বেছে নিতে পারে যা বর্তমানে বংশধর নয় যা অন্যান্য থ্রেড দ্বারা অনুকূলিত করা হচ্ছে। অতএব, এমন পিতামাতাদের সন্ধানের জন্য আমার অনুসন্ধান করা দরকার যা বর্তমানে অন্য থ্রেড দ্বারা লক করা হয়নি। মাস্টার থ্রেড মিটেক্স লক থাকায় অনুসন্ধানের সময় মিউটেক্সের স্থিতির কোনও ঝুঁকি নেই। স্পষ্টতই অন্যান্য সমাধান রয়েছে (আমি বর্তমানে বুলিয়ান পতাকা ব্যবহার করছি) তবে আমি ভেবেছিলাম যে মুটেক্স এই সমস্যাটির একটি যৌক্তিক সমাধান সরবরাহ করে, কারণ এটি আন্ত-থ্রেড সিঙ্ক্রোনাইজেশনের উদ্দেশ্যে বিদ্যমান।


42
আপনি সত্যিই যুক্তিযুক্তভাবে যাচাই করতে পারবেন না যে কোনও মিউটেক্স লক হয়েছে কি না, কারণ চেক করার পরে একটি ন্যানোসেকেন্ড এটি আনলক বা লক করতে পারে। সুতরাং আপনি যদি "যদি (মিটেক্স_আইস_লকড ()) ... লিখেছিলেন তবে মুটেক্স_আইস_লক সঠিক ফলাফলটি ফিরিয়ে দিতে পারে, তবে" যদি "কার্যকর হওয়ার সময়টি ভুল হয়।
gnasher729

1
এতে ^। আপনি কোন দরকারী তথ্য পেতে আশা করি is_locked?
বেহুদা

3
এটি একটি এক্সওয়াই-সমস্যার মতো অনুভব করে। আপনি কেন বাচ্চা তৈরির সময় পিতামাতার পুনঃব্যবহার রোধ করার চেষ্টা করছেন? আপনার কি কোনও চাহিদা আছে যে কোনও পিতা-মাতার কেবলমাত্র একটি সন্তান হতে পারে? আপনার লক এটি প্রতিরোধ করবে না। আপনার কি স্পষ্ট প্রজন্ম নেই? যদি তা না হয় তবে আপনি কি সচেতন হন যে ব্যক্তিরা দ্রুত অনুকূলিত হতে পারে তাদের উচ্চতর ফিটনেস রয়েছে, যেহেতু তারা প্রায়শই / আগে নির্বাচিত হতে পারে? আপনি যদি প্রজন্ম ব্যবহার করেন তবে আপনি কেন সমস্ত পিতামাতাকে সামনে রেখে বেছে নিচ্ছেন না, তারপরে থ্রেডগুলি অভিভাবকদের একটি সারি থেকে পুনরুদ্ধার করতে দিন? সন্তান জন্মদান কি এতটাই ব্যয়বহুল যে আপনার একাধিক থ্রেডের প্রয়োজন?
আমন

10
@ কোয়ান্ট - আপনার উদাহরণ অ্যাপ্লিকেশনটিতে আপনার প্যারেন্ট অবজেক্ট মিউটেক্সগুলিকে মোটেও মিটেক্স হওয়ার দরকার নেই: আপনার যদি কোনও মাস্টার মিউটেক্স থাকে যা যখনই সেট করা থাকে তখন লক করা থাকে, আপনি কেবলমাত্র তার বোলিয়ান ভেরিয়েবলটি তাদের অবস্থানটি নির্দেশ করতে ব্যবহার করতে পারেন।
পেরিটা ব্রেটা

4
আমি প্রশ্নের শেষ বাক্যটির সাথে একমত নই। একটি সাধারণ বুলিয়ান মান এখানে মুটেক্সের চেয়ে অনেক বেশি পরিষ্কার। আপনি যদি কোনও পিতামাতার "ফেরত" দেওয়ার জন্য মাস্টার মুটেক্সকে লক করতে না চান তবে এটি একটি পারমাণবিক পুল করুন।
সেবাস্তিয়ান রেডল

উত্তর:


53

প্রস্তাবিত অপারেশনটিতে আমি কমপক্ষে দুটি গুরুতর সমস্যা দেখতে পাচ্ছি।

@ Gnasher729 দ্বারা একটি মন্তব্যে প্রথমটি উল্লেখ করা হয়েছে :

আপনি সত্যই যুক্তিযুক্তভাবে চুপ করতে পারবেন না যে কোনও মিউটেক্স লক হয়েছে কিনা, কারণ চেক করার পরে একটি ন্যানোসেকেন্ড এটি আনলক বা লক করতে পারে। সুতরাং আপনি যদি লিখে থাকেন if (mutex_is_locked ()) …তবে mutex_is_lockedসঠিক ফলাফলটি ফিরে আসতে পারে, তবে সময় ifকার্যকর হওয়ার পরে এটি ভুল।

কোনও মুটেক্সের সম্পত্তি "বর্তমানে তালাবদ্ধ" না হওয়ার একমাত্র উপায় হ'ল এটি নিজেই লক করুন।

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

যদি আমি সঠিকভাবে বুঝতে পারি তবে উভয় সমস্যাই আপনার বিশেষ ক্ষেত্রে হতাশ হয়ে উঠবে মাস্টার মিটেক্সকে লক করা থাকার জন্য ধন্যবাদ। তবে এটি আমার কাছে একটি সাধারণ ঘটনা বলে মনে হচ্ছে না তাই আমি মনে করি যে কমিটি একটি বিশেষ অনুষ্ঠান যোগ না করে সঠিক কাজ করেছে যা খুব বিশেষ পরিস্থিতিতে কিছুটা কার্যকর হতে পারে এবং অন্য সকলের ক্ষতি হতে পারে। (এর চেতনায়: "ইন্টারফেসগুলি সঠিকভাবে ব্যবহার করা সহজ এবং ভুলভাবে ব্যবহার করা কঠিন করুন” ")

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


ধন্যবাদ, এটি একটি ভাল উত্তর। আমি প্রস্তুত পিতামাতার একটি সারি বজায় রাখতে চাই না তার কারণ হ'ল আমার পিতামাতার যে ক্রম তৈরি হয়েছিল তা সংরক্ষণ করা দরকার (এটি তাদের জীবনকালকে নির্দেশ করে)। এটি সহজেই একটি লাইফো সারির সাহায্যে সম্পন্ন হয়। যদি আমি জিনিসগুলি আউট এবং আউট করা শুরু করি তবে আমাকে একটি পৃথক ক্রম মেকানিজম বজায় রাখতে হবে যা জিনিসগুলিকে জটিল করে তুলবে, সুতরাং বর্তমান পদ্ধতির approach
কোয়ান্ট

14
@quant: আপনি কিউ পিতামাতার প্রতি দুই উদ্দেশ্য থাকে, তাহলে আপনি এখন করতে পারেন দুই সারি ....

@ কোয়ান্ট: আপনি একবারে কোনও আইটেম মুছে ফেলছেন (সর্বাধিক) তবে সম্ভবত প্রতিটি একাধিকবার প্রক্রিয়াজাতকরণ করছেন, তাই আপনি সাধারণ ক্ষেত্রে ব্যয় করে বিরল কেসটি অনুকূল করে তুলছেন। এটি খুব কমই কাম্য।
জেরি কফিন

2
তবে বর্তমান থ্রেডটি মিটেক্সটিকে লক করেছে কিনা তা জিজ্ঞাসা করা যুক্তিসঙ্গত।
সীমিত প্রায়শ্চিত্ত

টুইটসমূহ এই মুটেক্সটি করতে অতিরিক্ত তথ্য (থ্রেড আইডি) সংরক্ষণ করতে হবে, এটি ধীর করে তোলে। পুনরাবৃত্তিমূলক মুটেক্সেসটি ইতিমধ্যে এটি করে আপনার পরিবর্তে তাদের উচিত।
স্টেসিগার্ল

9

দেখে মনে হচ্ছে যে আপনি কোনও অপ্টিমাইজেশান সমস্যার অ্যাক্সেস লক না করে মাধ্যমিক মুটিেক্সগুলি ব্যবহার করছেন তবে একটি অনুকূলকরণের সমস্যাটি এখনই অনুকূলিত করা হচ্ছে কিনা তা নির্ধারণ করতে।

এটি সম্পূর্ণ অপ্রয়োজনীয়। আমার এমন সমস্যাগুলির একটি তালিকা রয়েছে যাগুলির অনুকূলকরণের প্রয়োজন, এই মুহুর্তে অনুকূলিত হওয়া সমস্যার একটি তালিকা এবং অনুকূলিত হওয়া সমস্যার একটি তালিকা রয়েছে। (আক্ষরিকভাবে "তালিকা" নেবেন না, এটি কোনও উপযুক্ত ডেটা স্ট্রাকচারের অর্থ বোঝায়)।

অব্যবহিত সমস্যার তালিকায় একটি নতুন সমস্যা যুক্ত করার বা একটি তালিকা থেকে অন্য তালিকায় কোনও সমস্যা স্থানান্তরিত করার কাজগুলি একক "মাস্টার" মিটেক্সের সুরক্ষায় করা হবে।


1
আপনি কি মনে করেন না যে কোনও ধরণের অবজেক্টটি এই std::mutexজাতীয় ডেটা কাঠামোর জন্য উপযুক্ত?
কোয়ান্ট

2
@ কোয়ান্ট - না std::mutexঅপারেটিং-সিস্টেমের সংজ্ঞায়িত মিউটেক্স প্রয়োগের উপর নির্ভর করে যা ভালভাবে সংস্থান করতে পারে (যেমন হ্যান্ডলগুলি) যা বরাদ্দকরণ এবং / বা পরিচালনা করতে সীমাবদ্ধ এবং ধীর। অভ্যন্তরীণ ডেটা স্ট্রাকচারটিতে অ্যাক্সেস লক করতে একটি একক মুটেক্স ব্যবহার করা সম্ভবত আরও বেশি দক্ষ এবং সম্ভবত আরও মাপেরযোগ্য।
পেরিটা ব্রেটাটা

1
কন্ডিশনের ভেরিয়েবলগুলিও বিবেচনা করুন। তারা এ জাতীয় প্রচুর ডেটা স্ট্রাকচার তৈরি করতে পারে।
কর্ট অ্যামোন - মোনিকা

2

অন্যরা যেমন বলেছে, কোনও is_lockedমিটেক্সের কোনও উপকার হয় এমন কোনও ব্যবহারের ঘটনা নেই , তাই ফাংশনটি বিদ্যমান নেই।

কেস আপনার সাথে একটি সমস্যা ভোগ করছি অবিশ্বাস্যভাবে সাধারণ, এটি মূলত কি কর্মী থ্রেড, না যা এক, যদি না থ্রেডের সবচেয়ে সাধারণ বাস্তবায়ন।

এটিতে 10 টি বাক্স সহ আপনার একটি বালুচর রয়েছে। এই বাক্সগুলির সাথে আপনার 4 জন কর্মী কাজ করছেন। 4 কর্মীরা বিভিন্ন বাক্সে কাজ করছেন তা আপনি কীভাবে নিশ্চিত করবেন? প্রথম শ্রমিক শেল্ফটিতে কাজ শুরু করার আগে একটি বাক্সটি নিয়ে যায়। দ্বিতীয় কর্মী তাকটিতে 9 টি বাক্স দেখেন।

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


1

উপরে 5gon12eder এর উত্তরে প্রদত্ত দুটি কারণ ছাড়াও, আমি যুক্ত করতে চাই যে এটি প্রয়োজনীয় বা পছন্দসই নয়।

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

আপনার যদি মিউটেক্স দ্বারা সুরক্ষিত ভাগ করা সংস্থান অ্যাক্সেস করার প্রয়োজন হয় এবং আপনি ইতিমধ্যে মিটেক্সটি ধরে রাখছেন না, তবে আপনাকে মুটেক্স অর্জন করতে হবে। অন্য কোনও বিকল্প নেই, অন্যথায় আপনার প্রোগ্রামের যুক্তি সঠিক নয়।
আপনি গ্রহণযোগ্য বা inacceptable ব্লক, উভয় ক্ষেত্রে পেতে পারে lock()বা try_lock()আচরণ যদি আপনি চান দেব। ইতিবাচকভাবে এবং সন্দেহ ছাড়াই আপনাকে যা জানা দরকার তা হ'ল আপনি সফলভাবে মিউটেক্স অর্জন করেছেন কিনা (আপনাকে ফেরতের মান try_lockআপনাকে বলে)। অন্য কেউ এটি ধরে রেখেছে বা আপনি কোনও উত্সাহব্যঞ্জী ব্যর্থতা পেয়েছেন কিনা তা অনিবার্য।

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


1
লক করার জন্য বর্তমানে উপলব্ধ সংস্থানগুলিতে যদি আমি র‌্যাঙ্কিং অপারেশন করতে চাই তবে কী হবে?
কোয়ান্ট

তবে কি এমন কিছু ঘটবে যা বাস্তবসম্মত? আমি বরং অস্বাভাবিক মনে করি। আমি বলব যে কোনও একটি সংস্থান ইতিমধ্যে কিছু অভ্যন্তরীণ ধরণের র‌্যাঙ্কিং রয়েছে, তবে আপনাকে প্রথমে আরও গুরুত্বপূর্ণ একটি (লকটি অর্জন) করতে হবে need উদাহরণ: রেন্ডারিংয়ের আগে পদার্থবিজ্ঞানের সিমুলেশন আপডেট করতে হবে। অথবা, র‌্যাঙ্কিং কমবেশি ইচ্ছাকৃত, এরপরে আপনি try_lockপ্রথম সংস্থানটিও করতে পারেন এবং যদি এটি ব্যর্থ হয় তবে দ্বিতীয়টি চেষ্টা করুন। উদাহরণ: ডাটাবেস সার্ভারে তিনটি ধ্রুবক, পুলযুক্ত সংযোগ এবং আপনার একটি আদেশ পাঠাতে একটি ব্যবহার করতে হবে।
দামন

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

@ পেরিটাব্রেটা আমার প্রোগ্রামটি ইচ্ছাকৃতভাবে অনির্দিষ্ট। আমি এখন দেখছি যে এই বৈশিষ্ট্যটি সাধারণ নয়, তাই এর মতো বৈশিষ্ট্যগুলি বাদ দেওয়া আমি বুঝতে পারি is_locked()যে এরূপ আচরণের সুবিধার্থে।
কোয়ান্ট

@ পরিমাণ র‌্যাঙ্কিং এবং লক করা সম্পূর্ণ পৃথক সমস্যা। আপনি যদি কোনওভাবে কোনও লক দিয়ে কোনও সারি বাছাই বা পুনরায় অর্ডার করতে চান তবে এটি লক করুন, বাছাই করুন, তারপরে এটি আনলক করুন। আপনার যদি প্রয়োজন হয় is_lockedতবে আপনার মনে রাখা সমস্যার চেয়ে আপনার সমস্যার আরও ভাল সমাধান বিদ্যমান।
পিটার

1

আপনি ডিফল্ট মেমরি ক্রমের সাথে অ্যাটমিক_ফ্ল্যাগ ব্যবহার করতে চাইছেন । এটিতে ডেটা দৌড় নেই এবং কখনও কখনও একাধিক আনলক কলগুলির সাথে মিটেক্সের মতো ব্যতিক্রম ছোঁড়ে না (এবং অনিয়ন্ত্রিতভাবে বিসর্জন দেয়, আমি যুক্ত করতে পারি ...)। বিকল্পভাবে, এখানে পারমাণবিক (যেমন পারমাণবিক [বুল] বা পারমাণবিক [ইনট] (ত্রিভুজ বন্ধনী সহ, [[] নয়)) রয়েছে, যার লোড এবং তুলনা_ এক্সচেঞ্জ_স্ট্রংয়ের মতো দুর্দান্ত ফাংশন রয়েছে।


1

আমি এর জন্য একটি ব্যবহার-কেস যুক্ত করতে চাই: এটি একটি অভ্যন্তরীণ ফাংশনটিকে পূর্ব শর্ত হিসাবে / নিশ্চিত করার জন্য যে আহ্বানকারী প্রকৃতপক্ষে লকটি ধরেছে তা নিশ্চিত করতে সক্ষম করবে।

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

class SynchronizedClass
{

public:

void publicFunc()
{
  std::lock_guard<std::mutex>(_mutex);

  internalFuncA();
}

// A lot of code

void newPublicFunc()
{
  internalFuncA(); // whops, forgot to acquire the lock
}


private:

void internalFuncA()
{
  assert(_mutex.is_locked_by_this_thread());

  doStuffWithLockedResource();
}

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