Latest web development tutorials

C ++ Многопоточность

Многопоточность является специализированной формой многозадачности, многозадачность позволяет дать компьютеру запускать два и более программ. В общем, два типа многозадачности: основанный на процессах и нитей на основе.

  • Процесс на основе многозадачности программа выполняется одновременно.
  • Обработка резьбы на основе многозадачности является параллельное выполнение одного и того же фрагмента программы.

Многопоточная программа содержит две или более частей, которые могут работать одновременно. Такая программа для каждой части называется нить, каждый поток определяет отдельный путь выполнения.

C ++ не включает в себя встроенную поддержку многопоточных приложений. Вместо этого, он полностью зависит от операционной системы, чтобы обеспечить эту функциональность.

В этом руководстве предполагается, что вы используете операционную систему Linux, мы хотим использовать POSIX написать многопоточную программу C ++. API POSIX Threads или Pthreads могут быть предоставлены на нескольких типах систем Unix POSIX, такие, как FreeBSD, NetBSD, GNU / Linux, Mac OS X и Solaris.

Создание потока

Следующая программа, мы можем использовать его для создания 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 () функция создает пять потоков, каждый выход "Hello 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 () функция создает пять потоков, а также принимать входящие параметры. Каждая нить печатает "Hello!" 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 () подпрограммы препятствовать вызывающей программе до указанного ThreadId поток не прекращается. При создании нити, это атрибут определяет, подключен ли он (присоединяемые) или съемной (отдельно). Определить только создать поток, который может быть подключен может быть подключен. Если поток создается определяется как разъемные, он никогда не может быть подключен.

Этот пример демонстрирует, как использовать функцию 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.