Latest web development tutorials

C ++ خاصية تعدد

خاصية تعدد هو نوع خاص من تعدد المهام، متعددة المهام تسمح السماح للتشغيل الكمبيوتر اثنين أو أكثر من البرامج. بشكل عام، نوعين من تعدد المهام: القائم على موضوع على أساس عملية و.

  • يتم تنفيذ برنامج متعدد المهام على أساس عملية في نفس الوقت.
  • تعدد المهام على أساس موضوع المعالجة هي التنفيذ المتزامن لجزء نفس البرنامج.

ويتضمن برنامج مؤشرات اثنين أو أكثر من الأجزاء التي يمكن تشغيلها في وقت واحد. ويسمى هذا البرنامج لكل جزء الموضوع، ويعرف كل موضوع مسار منفصل التنفيذ.

لا يشمل C ++ أي المدمج في دعم لتطبيقات متعددة الخيوط. بدلا من ذلك، تعتمد اعتمادا كليا على نظام التشغيل لتوفير هذه الوظيفة.

يفترض هذا البرنامج التعليمي الذي كنت تستخدم نظام التشغيل لينكس، ونحن نريد لاستخدام POSIX إرسال برنامج مؤشرات C ++. ويمكن توفير API POSIX المواضيع أو بثريدس على أنواع متعددة من أنظمة يونكس POSIX المتاحة، مثل فري، نت بي، جنو / لينكس، نظام التشغيل Mac OS X، وسولاريس.

إنشاء موضوع

البرنامج التالي، يمكننا استخدامها لإنشاء المواضيع POSIX:

#include <pthread.h>
pthread_create (thread, attr, start_routine, arg) 

هنا، pthread_create يخلق موضوع جديد وجعله قابل للتنفيذ.وفيما يلي وصفا للمعلمات:

参数 描述
thread 指向线程标识符指针。
attr 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。
start_routine 线程运行函数起始地址,一旦线程被创建就会执行。
arg 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。

عند إنشاء موضوع ناجحة، تقوم الدالة بإرجاع 0، إذا كانت قيمة العائد من 0 إلى أن فشل في إنشاء موضوع.

إنهاء موضوع

استخدم الإجراء التالي، يمكننا استخدامها لإنهاء المواضيع POSIX:

#include <pthread.h>
pthread_exit (status) 

هنا، pthread_exit تستخدم للخروج صراحة موضوع.في ظل الظروف العادية، يتم استدعاء الدالة pthread_exit () عند انجاز المهمة دون الحاجة إلى الاستمرار في الوجود بعد موضوع.

إذا الرئيسية () قبل نهاية الخيط الذي خلقت، والمخارج من خلال pthread_exit ()، ثم سيستمر المواضيع الأخرى لتنفيذه. خلاف ذلك، وأنها ستكون في الرئيسية () في نهاية إنهاء تلقائيا.

أمثلة

يستخدم المثال التالي رمز بسيط pthread_create () الدالة بإنشاء خمسة المواضيع، كل الانتاج "مرحبا w3big!"

#include <iostream>
// 必须的头文件是
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

// 线程的运行函数
void* say_hello(void* args)
{
    cout << "Hello w3big!" << endl;
}

int main()
{
    // 定义线程的 id 变量,多个变量使用数组
    pthread_t tids[NUM_THREADS];
    for(int i = 0; i < NUM_THREADS; ++i)
    {
        //参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
        int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
        if (ret != 0)
        {
           cout << "pthread_create error: error_code=" << ret << endl;
        }
    }
    //等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
    pthread_exit(NULL);
}

استخدام مكتبة -lpthread ترجمة البرنامج التالي:

$ g++ test.cpp -lpthread -o test.o

الآن، فإن تنفيذ برنامج تنتج النتائج التالية:

$ ./test.o
Hello w3big!
Hello w3big!
Hello w3big!
Hello w3big!
Hello w3big!

يستخدم المثال التالي رمز بسيط pthread_create () الدالة بإنشاء خمسة المواضيع، واستقبال المعلمات واردة. كل موضوع بطباعة "مرحبا w3big!" رسالة، وإخراج المعلمات الواردة، ومن ثم استدعاء pthread_exit () إنهاء الموضوع.

//文件名:test.cpp

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS     5

void *PrintHello(void *threadid)
{  
   // 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取
   int tid = *((int*)threadid);
   cout << "Hello w3big! 线程 ID, " << tid << endl;
   pthread_exit(NULL);
}

int main ()
{
   pthread_t threads[NUM_THREADS];
   int indexes[NUM_THREADS];// 用数组来保存i的值
   int rc;
   int i;
   for( i=0; i < NUM_THREADS; i++ ){      
      cout << "main() : 创建线程, " << i << endl;
      indexes[i] = i; //先保存i的值
      // 传入的时候必须强制转换为void* 类型,即无类型指针        
      rc = pthread_create(&threads[i], NULL, 
                          PrintHello, (void *)&(indexes[i]));
      if (rc){
         cout << "Error:无法创建线程," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

الآن تجميع وتنفيذ البرنامج سوف تؤدي إلى النتائج التالية:

$ g++ test.cpp -lpthread -o test.o
$ ./test.o
main() : 创建线程, 0
main() : 创建线程, 1
main() : 创建线程, 2
main() : 创建线程, 3
main() : 创建线程, 4
Hello w3big! 线程 ID, 4
Hello w3big! 线程 ID, 3
Hello w3big! 线程 ID, 2
Hello w3big! 线程 ID, 1
Hello w3big! 线程 ID, 0

تمرير المعلمات إلى الموضوع

يوضح هذا المثال كيفية تمرير متعددة هيكل المعلمات. يمكنك تمرير أي نوع من البيانات في رد موضوع، لأنه يشير إلى الفراغ، كما هو مبين في الأمثلة التالية:

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS     5

struct thread_data{
   int  thread_id;
   char *message;
};

void *PrintHello(void *threadarg)
{
   struct thread_data *my_data;

   my_data = (struct thread_data *) threadarg;

   cout << "Thread ID : " << my_data->thread_id ;
   cout << " Message : " << my_data->message << endl;

   pthread_exit(NULL);
}

int main ()
{
   pthread_t threads[NUM_THREADS];
   struct thread_data td[NUM_THREADS];
   int rc;
   int i;

   for( i=0; i < NUM_THREADS; i++ ){
      cout <<"main() : creating thread, " << i << endl;
      td[i].thread_id = i;
      td[i].message = "This is message";
      rc = pthread_create(&threads[i], NULL,
                          PrintHello, (void *)&td[i]);
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

عندما يتم ترجمة التعليمات البرمجية أعلاه وتنفيذها، وتنتج النتائج التالية:

$ g++ -Wno-write-strings test.cpp -lpthread -o test.o
$ ./test.o
main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message

ربط وفصل موضوع

يمكننا استخدام الوظيفتين التالية للاتصال أو ترابط منفصلة:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join () روتين يعيق برنامج الاستدعاء حتى إنهاء موضوع رقم الموضوع المحدد. عند إنشاء موضوع، انها تحدد سمة سواء كان متصلا (joinable) أو انفصال (فصل). فقط تعريف إنشاء موضوع التي يمكن توصيلها يمكن توصيلها. إذا تم تعريف موضوع تم إنشاؤه للانفصال كما أنه لا يمكن أبدا أن تكون متصلا.

يوضح هذا المثال كيفية استخدام وظيفة pthread_join () لانتظار موضوع الانتهاء.

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS     5

void *wait(void *t)
{
   int i;
   long tid;

   tid = (long)t;

   sleep(1);
   cout << "Sleeping in thread " << endl;
   cout << "Thread with id : " << tid << "  ...exiting " << endl;
   pthread_exit(NULL);
}

int main ()
{
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // 初始化并设置线程为可连接的(joinable)
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i=0; i < NUM_THREADS; i++ ){
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, wait, (void *)i );
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // 删除属性,并等待其他线程
   pthread_attr_destroy(&attr);
   for( i=0; i < NUM_THREADS; i++ ){
      rc = pthread_join(threads[i], &status);
      if (rc){
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}

عندما يتم ترجمة التعليمات البرمجية أعلاه وتنفيذها، وتنتج النتائج التالية:

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread 
Thread with id : 4  ...exiting 
Sleeping in thread 
Thread with id : 3  ...exiting 
Sleeping in thread 
Thread with id : 2  ...exiting 
Sleeping in thread 
Thread with id : 1  ...exiting 
Sleeping in thread 
Thread with id : 0  ...exiting 
Main: completed thread id :0  exiting with status :0
Main: completed thread id :1  exiting with status :0
Main: completed thread id :2  exiting with status :0
Main: completed thread id :3  exiting with status :0
Main: completed thread id :4  exiting with status :0
Main: program exiting.