সি ++ এ থ্রেডিংয়ের সহজ উদাহরণ


391

কেউ কি সি ++ এ দুটি (অবজেক্ট ওরিয়েন্টেড) থ্রেড শুরু করার সাধারণ উদাহরণ পোস্ট করতে পারেন?

আমি প্রকৃত সি ++ থ্রেড অবজেক্টগুলির সন্ধান করছি যা আমি সি-স্টাইলের থ্রেড লাইব্রেরি কল করার বিপরীতে চালানো পদ্ধতিগুলি (বা অনুরূপ কিছু) প্রসারিত করতে পারি।

আমি যে কোনও ওএস নির্দিষ্ট অনুরোধ রেখেছিলাম এই আশায় যে যে উত্তর দিয়েছে সে ক্রস প্ল্যাটফর্ম লাইব্রেরি ব্যবহার করে উত্তর দেবে। আমি এখন এটি স্পষ্টভাবে তৈরি করছি।


উত্তর:


560

আপনি একটি ফাংশন তৈরি করুন যা আপনি থ্রেডটি কার্যকর করতে চান, যেমন:

void task1(std::string msg)
{
    std::cout << "task1 says: " << msg;
}

এখন threadঅবজেক্টটি তৈরি করুন যা শেষ পর্যন্ত উপরের ফাংশনটিকে অনুরোধ করবে:

std::thread t1(task1, "Hello");

( #include <thread>আপনার std::threadক্লাসটি অ্যাক্সেস করতে হবে )

কনস্ট্রাক্টরের আর্গুমেন্টগুলি ফাংশনটি থ্রেডটি কার্যকর করবে এবং ফাংশনের পরামিতিগুলি অনুসরণ করবে। থ্রেডটি স্বয়ংক্রিয়ভাবে নির্মাণের পরে শুরু হয়।

পরে যদি আপনি ফাংশনটি সম্পাদন করে থ্রেডটির জন্য অপেক্ষা করতে চান তবে কল করুন:

t1.join(); 

(যোগদানের অর্থ হ'ল যে থ্রেডটি নতুন থ্রেডকে আহ্বান করেছিল তার নতুন কার্যকর হওয়ার আগেই এটি শেষ হওয়ার জন্য অপেক্ষা করবে) execution


কোড

#include <string>
#include <iostream>
#include <thread>

using namespace std;

// The function we want to execute on the new thread.
void task1(string msg)
{
    cout << "task1 says: " << msg;
}

int main()
{
    // Constructs the new thread and runs it. Does not block execution.
    thread t1(task1, "Hello");

    // Do other things...

    // Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
    t1.join();
}

স্টাডি :: থ্রেড সম্পর্কে আরও তথ্য এখানে

  • জিসিসিতে, সংকলন করুন -std=c++0x -pthread
  • এটি কোনও অপারেটিং-সিস্টেমের জন্য কাজ করা উচিত, আপনার সংকলকটি (সি ++ 11) বৈশিষ্ট্যটিকে সমর্থন করে granted

4
@ প্রিজা 8 ভিএস 10 সি ++ 11 এ অনেকগুলি বৈশিষ্ট্য সমর্থন করে না। ভিএস 12 এবং ভিএস 13 সমর্থন থ্রেড।
জোড্যাগ

3
"7. below এর নীচে জিসিসির সংস্করণগুলিতে মন্তব্য করুন -std=c++0x(এর পরিবর্তে -std=c++0x)" আমি বিশ্বাস করি দ্বিতীয় "সি ++ ০x" এর পরিবর্তে "সি ++ ১১" হওয়া উচিত, তবে সম্পাদনা খুব ছোট হওয়ায় এটি পরিবর্তন সম্ভব নয়।
জেন্টারুনিক্স

1
@ মাস্টারমাস্টিক স্ট্যান্ড :: থ্রেড টি 1 (টাস্ক 1, "হ্যালো") এর পরিবর্তে ফাংশনটির রেফারেন্সটি পাস করে std :: থ্রেড টি 1 (& টাস্ক 1, "হ্যালো") ব্যবহার করলে কী পার্থক্য হবে? এক্ষেত্রে আমাদের ফাংশনটিকে পয়েন্টার হিসাবে ঘোষণা করা উচিত?
ব্যবহারকারী2452253

3
@ user2452253 আপনি যদি "কার্য 1" পাস করেন তবে আপনি যে ফাংশনটি সম্পাদন করতে চান তার জন্য একটি পয়েন্টারটি পাস করেন (যা ভাল)। যদি আপনি "এবং টাস্ক 1" পাস করেন তবে আপনি কোনও ফাংশনের পয়েন্টারে একটি পয়েন্টারটি পাস করেন এবং ফলাফলগুলি সম্ভবত এত সুন্দর এবং খুব অপরিজ্ঞাত হবে না (এটি একের পর এক এলোমেলো নির্দেশাবলী কার্যকর করার চেষ্টা করার মতো হবে the সঠিক সম্ভাবনার সাথে আপনি সম্ভবত জাহান্নামের প্রবেশদ্বারটি খুলুন)। আপনি কেবলমাত্র ফাংশন পয়েন্টারটি পাস করতে চান (ফাংশনটি শুরু হয় এমন ঠিকানার মান সহ একটি পয়েন্টার)। যদি এটি জিনিস পরিষ্কার না করে, আমাকে জানান, এবং শুভকামনা!
মাস্টারমাস্টিক

2
@ কুরিয়াসগুয়ে ওয়েল, এটি করার সঠিক উপায়টি হল আপনি যে ফাংশনটি চালাতে চান তার একটি পয়েন্টার পাস করা। এই ক্ষেত্রে ফাংশন হয় task1। সুতরাং ফাংশন পয়েন্টার দ্বারা চিহ্নিত করা হয় task1। তবে এটি আনার জন্য আপনাকে ধন্যবাদ কারণ আমি বিশ্বাস করি যে আমি ভুল ছিলাম এবং এটির সমতুল্য &task1, সুতরাং আপনি কোন ফর্মটি লিখতে পছন্দ করেন তা বিবেচ্য নয় (যদি তাই হয় তবে আমি অনুমান করি যে ফাংশনটির পয়েন্টারটিতে নির্দেশকটি রয়েছে &&task1- এটি খারাপ হবে) )। প্রাসঙ্গিক প্রশ্ন
মাস্টারমাস্টিক

80

ঠিক আছে, প্রযুক্তিগতভাবে এই জাতীয় কোনও বস্তু সি-স্টাইলের থ্রেড লাইব্রেরির উপরে নির্মিত হবে কারণ সি ++ কেবলমাত্র std::threadসি ++ 0x এর একটি স্টক মডেল নির্দিষ্ট করেছে , যা কেবল পেরেকযুক্ত ছিল এবং এখনও কার্যকর করা হয়নি। সমস্যাটি কিছুটা সিস্টেমিক, প্রযুক্তিগতভাবে বিদ্যমান সি ++ মেমরি মডেলটি 'এর আগে ঘটে' এর ক্ষেত্রে সবার জন্য সুস্পষ্ট সংজ্ঞাযুক্ত শব্দার্থককে অনুমতি দেওয়ার পক্ষে যথেষ্ট কঠোর নয়। হ্যানস বোহম কিছুক্ষণ আগে এই বিষয়ের উপর একটি নিবন্ধ লিখেছিলেন এবং এই বিষয়ের উপর সি ++ 0x স্ট্যান্ডার্ডকে হাতুড়ি তৈরিতে সহায়ক ভূমিকা পালন করেছিলেন।

http://www.hpl.hp.com/techreports/2004/HPL-2004-209.html

এটি বলেছে যে বেশ কয়েকটি ক্রস-প্ল্যাটফর্ম থ্রেড সি ++ লাইব্রেরি রয়েছে যা অনুশীলনে ঠিকঠাক কাজ করে। ইন্টেল থ্রেড বিল্ডিং ব্লকগুলিতে একটি টিবিবি :: থ্রেড অবজেক্ট রয়েছে যা ঘনিষ্ঠভাবে সি ++ 0x স্ট্যান্ডার্ডের সাথে সজ্জিত এবং বুস্টের একটি বুস্ট :: থ্রেড লাইব্রেরি রয়েছে যা একই কাজ করে।

http://www.threadingbuildingblocks.org/

http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html

বুস্ট :: থ্রেড ব্যবহার করে আপনি এমন কিছু পাবেন:

#include <boost/thread.hpp>

void task1() { 
    // do stuff
}

void task2() { 
    // do stuff
}

int main (int argc, char ** argv) {
    using namespace boost; 
    thread thread_1 = thread(task1);
    thread thread_2 = thread(task2);

    // do other stuff
    thread_2.join();
    thread_1.join();
    return 0;
}

8
বুস্ট থ্রেড দুর্দান্ত - আমার একটাই সমস্যা ছিল যে আপনি (যখন আমি এটি শেষবার ব্যবহার করেছি) প্রকৃত স্থানীয় আন্ডারলাইং থ্রেড হ্যান্ডেলটি অ্যাক্সেস করতে পারিনি কারণ এটি একটি প্রাইভেট ক্লাস সদস্য ছিল! উইন 32 এ একটি টন স্টাফ রয়েছে যার জন্য আপনার থ্রেডহ্যান্ডেল দরকার, তাই হ্যান্ডেলটি সর্বজনীন করতে আমরা এটি টুইট করি।
অরিয়ন এডওয়ার্ডস

4
বুস্ট :: থ্রেডের সাথে আরেকটি সমস্যা হ'ল আমার মনে আছে যে নতুন থ্রেডের স্ট্যাকের আকার নির্ধারণ করার স্বাধীনতা আপনার নেই - এটি এমন একটি বৈশিষ্ট্য যা শোকস্বরূপ সি ++ 0x মানের অন্তর্ভুক্ত নয়।
এডওয়ার্ড কেএমইটিটি

এই কোডটি আমাকে এই উত্সাহ দেয়: এই রেখার জন্য অননুকলযোগ্য ব্যতিক্রম: থ্রেড থ্রেড_1 = থ্রেড (টাস্ক 1); সম্ভবত এটি কারণ আমি একটি পুরানো সংস্করণ (1.32) ব্যবহার করছি।
ফ্র্যাঙ্ক

এই সুযোগে টাস্ক 1 ঘোষণা করা হয়নি?
জ্যাক গ্যাস্টন

20

POSIX অপারেটিং সিস্টেমের জন্য একটি পসিক্স লাইব্রেরি রয়েছে। সামঞ্জস্যতা পরীক্ষা করুন

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

void *task(void *argument){
      char* msg;
      msg = (char*)argument;
      std::cout<<msg<<std::endl;
}

int main(){
    pthread_t thread1, thread2;
    int i1,i2;
    i1 = pthread_create( &thread1, NULL, task, (void*) "thread 1");
    i2 = pthread_create( &thread2, NULL, task, (void*) "thread 2");

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    return 0;

}

-pthread সঙ্গে সংকলন

http://en.wikipedia.org/wiki/POSIX_Threads


18
#include <thread>
#include <iostream>
#include <vector>
using namespace std;

void doSomething(int id) {
    cout << id << "\n";
}

/**
 * Spawns n threads
 */
void spawnThreads(int n)
{
    std::vector<thread> threads(n);
    // spawn n threads:
    for (int i = 0; i < n; i++) {
        threads[i] = thread(doSomething, i + 1);
    }

    for (auto& th : threads) {
        th.join();
    }
}

int main()
{
    spawnThreads(10);
}

13

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

Class.h

class DataManager
{
public:
    bool hasData;
    void getData();
    bool dataAvailable();
};

Class.cpp

#include "DataManager.h"

void DataManager::getData()
{
    // perform background data munging
    hasData = true;
    // be sure to notify on the main thread
}

bool DataManager::dataAvailable()
{
    if (hasData)
    {
        return true;
    }
    else
    {
        std::thread t(&DataManager::getData, this);
        t.detach(); // as opposed to .join, which runs on the current thread
    }
}

নোট করুন যে এই উদাহরণটি মিটেক্স বা লকিংয়ের মধ্যে পড়ে না।


2
এই পোস্ট করার জন্য ধন্যবাদ। নোট করুন যে উদাহরণ পদ্ধতিতে কোনও থ্রেড চাওয়ার সাধারণ ফর্মটি এরকম কিছু হয়: Foo f; স্টাড :: থ্রেড টি (& ফু :: রান করুন, এবং এফ, আরগস ...); (যেখানে ফু এমন একটি শ্রেণি যেখানে সদস্য ফাংশন হিসাবে 'রান ()' থাকে)।
জে এলস্টন

এই পোস্ট করার জন্য ধন্যবাদ। আমি কেন গুরুত্ব সহকারে বুঝতে পারি না যে সমস্ত থ্রেডিং উদাহরণ বিশ্বব্যাপী ফাংশন ব্যবহার করে।
hkBattousai

9

গ্লোবাল নেমস্প্যাকগুলিতে কেউ পৃথক ফাংশন না চাইলে আমরা থ্রেড তৈরির জন্য ল্যাম্বদা ফাংশন ব্যবহার করতে পারি।

ল্যাম্বদা ব্যবহার করে থ্রেড তৈরির একটি বড় সুবিধা হ'ল আমাদের আর্গুমেন্টের তালিকা হিসাবে স্থানীয় পরামিতিগুলি পাস করার দরকার নেই। আমরা একই জন্য ক্যাপচার তালিকাটি ব্যবহার করতে পারি এবং ল্যাম্বদার ক্লোজার সম্পত্তি জীবনচক্রের যত্ন নেবে।

এখানে একটি নমুনা কোড

int main() {
    int localVariable = 100;

    thread th { [=](){
        cout<<"The Value of local variable => "<<localVariable<<endl;
    }}

    th.join();

    return 0;
}

এতদূর, আমি সি ++ ল্যাম্বডাসকে পেয়েছি বিশেষত সহজ থ্রেড ফাংশনের জন্য থ্রেড তৈরির সেরা উপায় be


8

এটি মূলত আপনি যে লাইব্রেরিটি ব্যবহার করবেন তা নির্ভর করে on উদাহরণস্বরূপ, আপনি wxWidgets লাইব্রেরি ব্যবহার করেন, একটি থ্রেড তৈরির মত দেখতে হবে:

class RThread : public wxThread {

public:
    RThread()
        : wxThread(wxTHREAD_JOINABLE){
    }
private:
    RThread(const RThread &copy);

public:
    void *Entry(void){
        //Do...

        return 0;
    }

};

wxThread *CreateThread() {
    //Create thread
    wxThread *_hThread = new RThread();

    //Start thread
    _hThread->Create();
    _hThread->Run();

    return _hThread;
}

যদি আপনার মূল থ্রেডটি ক্রিয়েটথ্রেড পদ্ধতিতে কল করে, আপনি একটি নতুন থ্রেড তৈরি করবেন যা আপনার "এন্ট্রি" পদ্ধতিতে কোডটি কার্যকর করা শুরু করবে। এটি যুক্ত হতে বা থামাতে আপনাকে বেশিরভাগ ক্ষেত্রে থ্রেডের একটি রেফারেন্স রাখতে হবে। এখানে আরও তথ্য: ডাব্লুএক্সড্রেড ডকুমেন্টেশন


1
আপনি থ্রেড মুছতে ভুলে গেছেন। সম্ভবত আপনি একটি বিচ্ছিন্ন থ্রেড তৈরি করতে চেয়েছিলেন ?
aib

1
হ্যাঁ, ঠিক আছে, আমি বর্তমানে যে কোডটি নিয়ে কাজ করছি তা থেকে কোডটি বের করেছি এবং অবশ্যই থ্রেডের রেফারেন্সটি যোগ দেওয়া, থামাতে এবং পরে মুছে ফেলার জন্য কোথাও সংরক্ষণ করা হয়েছে। ধন্যবাদ। :)
LorenzCK
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.