আমি কখন স্টাড :: থ্রেড :: বিচ্ছিন্ন ব্যবহার করব?


140

std::threadআমার অ্যাপ্লিকেশনটি দ্রুত করার জন্য আমাকে কিছু সময় ব্যবহার করতে হবে। আমি জানি যে join()কোনও থ্রেড সমাপ্ত না হওয়া পর্যন্ত অপেক্ষা করে। এটি বোঝা সহজ, তবে এটি কল করা detach()এবং কল না করার মধ্যে পার্থক্য কী?

আমি ভেবেছিলাম এটি ছাড়া detach()থ্রেডের পদ্ধতিটি স্বাধীনভাবে একটি থ্রেড ব্যবহার করে কাজ করবে।

আলাদা করা হচ্ছে না:

void Someclass::Somefunction() {
    //...

    std::thread t([ ] {
        printf("thread called without detach");
    });

    //some code here
}

বিচ্ছিন্নতার সাথে কল করা:

void Someclass::Somefunction() {
    //...

    std::thread t([ ] {
        printf("thread called with detach");
    });

    t.detach();

    //some code here
}


উভয় stdএবং boostথ্রেডগুলি পসিক্স থ্রেডগুলির পরে কাছাকাছি detachএবং joinমডেল হয়েছে।
এন। 'সর্বনাম' মি।

উত্তর:


149

এর বিনাশকারী ইন std::thread, std::terminateযদি বলা হয়:

  • থ্রেড যোগদান করা হয়নি (সহ t.join())
  • এবং (বা t.detach()) দ্বারা বিচ্ছিন্ন ছিল না

সুতরাং, কার্যকর হওয়ার প্রবাহটি ডেস্ট্রাক্টরের কাছে পৌঁছানোর আগে আপনার সর্বদা হয় joinবা detachএকটি থ্রেড থাকা উচিত ।


যখন কোনও প্রোগ্রাম সমাপ্ত হয় (অর্থাত্‍ mainফিরে আসে) পটভূমিতে কার্যকর হওয়া পৃথক পৃথক থ্রেডগুলি অপেক্ষায় থাকে না; পরিবর্তে তাদের কার্যকরকরণ স্থগিত করা হয় এবং তাদের থ্রেড-স্থানীয় অবজেক্ট ধ্বংস হয়ে যায়।

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


সুতরাং, আপনি joinবা ব্যবহার করা উচিত detach?

  • ব্যবহার join
  • আপনার যদি আরও নমনীয়তা প্রয়োজন না হয় এবং আপনার নিজের উপর থ্রেড সমাপ্তির জন্য অপেক্ষা করার জন্য একটি সিঙ্ক্রোনাইজেশন প্রক্রিয়া সরবরাহ করতে ইচ্ছুক না হন তবে আপনি যে ক্ষেত্রে ব্যবহার করতে পারেনdetach

আমি যদি pthread_exit (NULL) কল করতাম; প্রধান () এর পরে প্রস্থান () প্রধান () থেকে কল করা হবে না এবং সুতরাং সমস্ত বিচ্ছিন্ন থ্রেড সম্পূর্ণ না হওয়া পর্যন্ত প্রোগ্রাম কার্যকর করা অব্যাহত থাকবে। তারপরে প্রস্থান () বলা হবে।
সাউথারটন

1
@ ম্যাথিউ, আমরা কেন স্টাড :: থ্রেডের ধ্বংসকারীদের সাথে যোগ দিতে পারি না?
জন স্মিথ

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

@ ম্যাথিউউ আমি মনে করি আপনার কাছে স্ট্যান্ড :: থ্রেডের ডেস্ট্রাক্টর পৌঁছানোর আগে কল (যোগ) বলতে চাইছেন। আপনি (এবং উচিত?) একটি বদ্ধ শ্রেণীর ধ্বংসকারীকে () যোগদান করতে পারেন?
হোসে কুইন্টেইরো

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

25

আপনি detachথ্রেডটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে না চাইলে কল করা উচিত joinতবে থ্রেডটি কেবল এটি শেষ না হওয়া পর্যন্ত চলতে থাকবে এবং তারপরে মূল থ্রেডটির জন্য বিশেষভাবে অপেক্ষা না করেই শেষ হবে।

detachমূলত বাস্তবায়ন করতে সক্ষম হওয়ার জন্য প্রয়োজনীয় সংস্থানগুলি মুক্তি দেবে join

যদি একটি থ্রেড বস্তুর তার জীবন শেষ হয় এবং কেউই এটা একটি মারাত্মক ত্রুটি joinকিংবা detachবলা হয়েছে; এই ক্ষেত্রে অনুরোধ terminateকরা হয়।


12
আপনার উল্লেখ করা উচিত, সেই টার্মিনেটটিকে ডাস্ট্রেক্টরতে ডাকা হয়, যদি থ্রেডটি না যোগ হয় বা আলাদা না হয়
nosid

11

আপনি যখন থ্রেডকে বিচ্ছিন্ন করেন তার অর্থ হল join()প্রস্থান করার আগে আপনার কাছে এটির দরকার নেই main()

থ্রেড লাইব্রেরি আসলে নীচে-মূল এই জাতীয় প্রতিটি থ্রেডের জন্য অপেক্ষা করবে তবে আপনার এটির যত্ন নেওয়া উচিত নয়।

detach()আপনার যখন কোনও কাজ পটভূমিতে করতে হয় তখন প্রধানত কার্যকর হয়, তবে আপনি এটি কার্যকর করার বিষয়ে চিন্তা করেন না। এটি সাধারণত কিছু লাইব্রেরির ক্ষেত্রে হয়। তারা নিঃশব্দে একটি পটভূমি কর্মী থ্রেড তৈরি করতে পারে এবং এটিকে বিচ্ছিন্ন করতে পারে যাতে আপনি এটি খেয়ালও করেন না।


এটি প্রশ্নের উত্তর দেয় না। উত্তরটি মূলত "আপনাকে বিচ্ছিন্ন করার সময় আপনি বিচ্ছিন্ন" বলে থাকে।
রুবেনভবি

7

এই উত্তরটি শিরোনামে প্রশ্নের উত্তর দেওয়া, joinএবং এর মধ্যে পার্থক্য ব্যাখ্যা করার পরিবর্তে detach। সুতরাং কখন std::thread::detachব্যবহার করা উচিত?

সঠিকভাবে রক্ষণাবেক্ষণে সি ++ কোড std::thread::detachমোটেও ব্যবহার করা উচিত নয়। প্রোগ্রামারকে অবশ্যই নিশ্চিত করা উচিত যে তৈরি করা সমস্ত থ্রেডগুলি কৃত্রিমভাবে সমস্ত অর্জিত সংস্থানগুলি ছেড়ে দেওয়ার এবং অন্যান্য প্রয়োজনীয় ক্লিনআপ ক্রিয়াকলাপ সম্পাদন করে exit এটি সূচিত করে যে অনুরোধ করে থ্রেডগুলির মালিকানা ছেড়ে দেওয়া detachকোনও বিকল্প নয় এবং তাই joinসমস্ত পরিস্থিতিতে ব্যবহার করা উচিত।

তবে কিছু অ্যাপ্লিকেশন পুরানো এবং প্রায়শই ভাল নকশাকৃত এবং সমর্থিত এপিআইগুলিতে নির্ভর করে যা অনির্দিষ্টকালের জন্য অবরুদ্ধকরণের কার্যাদি থাকতে পারে। অন্যান্য জিনিসগুলি ব্লক করা এড়াতে এই ফাংশনগুলির অনুরোধকে উত্সর্গীকৃত থ্রেডে স্থানান্তর করা একটি সাধারণ অভ্যাস is চূড়ান্তভাবে প্রস্থান করার জন্য এই জাতীয় থ্রেড করার কোনও উপায় নেই তাই এর ব্যবহারের ফলে joinকেবল প্রাথমিক থ্রেড ব্লক হয়ে যাবে। এটি এমন একটি পরিস্থিতি যখন ব্যবহার করা হ'ল গতিশীল স্টোরেজ সময়কাল সহ অবজেক্ট detachবরাদ্দ করা threadএবং তারপরে উদ্দেশ্যমূলকভাবে ফাঁস করা, এর জন্য কম খারাপ বিকল্প হবে।

#include <LegacyApi.hpp>
#include <thread>

auto LegacyApiThreadEntry(void)
{
    auto result{NastyBlockingFunction()};
    // do something...
}

int main()
{
    ::std::thread legacy_api_thread{&LegacyApiThreadEntry};
    // do something...
    legacy_api_thread.detach();
    return 0;
}

1

সিপ্রেফারেন্স.কম অনুসারে :

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

ডিটেচ কল করার পরে *thisআর কোনও থ্রেডের মালিক নেই।

উদাহরণ স্বরূপ:

  std::thread my_thread([&](){XXXX});
  my_thread.detach();

স্থানীয় ভেরিয়েবলটি লক্ষ্য করুন: my_threadএর আজীবন my_threadশেষ হয়ে গেলে এর ডেস্ট্রাক্টর std::threadডেকে আনা হবে এবং std::terminate()ডাস্ট্রাস্টারের মধ্যে ডাকা হবে।

তবে আপনি যদি ব্যবহার করেন তবে আপনার আর detach()ব্যবহার করা উচিত নয় my_thread, এমনকি যদি আজীবন my_threadশেষ হয়ে যায় তবে নতুন থ্রেডের কিছুই হবে না।


ঠিক আছে, আমি ফেরত নিতে এইমাত্র আমি যা বলেছিলাম @ TobySpeight।
DinoStray

1
নোট করুন যে আপনি যদি &ল্যাম্বডা ক্যাপচারে ব্যবহার করে থাকেন তবে আপনি রেফারেন্সের দ্বারা ঘেরের স্কোপের ভেরিয়েবলগুলি ব্যবহার করছেন - সুতরাং আপনারা নিশ্চিত হওয়া উচিত যে আপনার যে কোনও রেফারেন্সের জীবনকাল আপনার থ্রেডের জীবদ্দশার চেয়ে দীর্ঘ।
ডেভিডজে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.