Latest web development tutorials

C ++ Wielowątkowość

Wielowątkowość jest wyspecjalizowaną formą wielozadaniowych, wielozadaniowość pozwala niech uruchomić komputer z dwóch lub więcej programów. Ogólnie rzecz biorąc, dwa rodzaje wielozadaniowość: Proces oparte i nici na bazie.

  • Proces oparty na wielozadaniowość program jest wykonywany jednocześnie.
  • wielozadaniowość tworzenie wątku oparte jest równoczesna realizacja tego samego fragmentu programu.

Wielowątkowy program zawiera dwie lub więcej części, które mogą pracować jednocześnie. Taki program dla każdej części nazywa się wątku, każda nić tworzy oddzielną drogą wykonania.

C ++ nie zawiera wbudowane wsparcie dla aplikacji wielowątkowych. Zamiast tego, to jest całkowicie zależne od systemu operacyjnego, aby zapewnić tę funkcję.

Ten poradnik zakłada, że ​​używasz systemu operacyjnego Linux, chcemy wykorzystać POSIX napisać program w C ++ wielowątkowe. API POSIX Threads lub Pthreads mogą być dostarczone na wielu typach systemów Unix POSIX dostępne, takie jak FreeBSD, NetBSD, GNU / Linux, Mac OS X i Solaris.

Tworzenie wątku

Poniższy program, możemy używać go do tworzenia wątków POSIX:

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

Tutaj pthread_create tworzy nowy wątek i uczynić go wykonywalnym.Poniżej znajduje się opis parametrów:

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

Gdy wątek zostanie utworzony pomyślnie, funkcja zwraca 0, jeśli wartość zwracana 0 wskazuje, że nie udało się utworzyć wątku.

Zakończenie wątku

Użyj poniższej procedury, możemy użyć go do wypowiedzenia wątki POSIX:

#include <pthread.h>
pthread_exit (status) 

Tutaj pthread_exit używane jawnie zamknąć wątek.W normalnych okolicznościach, funkcja pthread_exit () jest wywoływana, gdy zadanie bez konieczności nadal istnieć po wątku.

Jeżeli głównym () do końca gwintu, który utworzył i wypływa pthread_exit (), a pozostałe nici będą w dalszym ciągu wykonania. W przeciwnym razie będą one w main () na końcu zostaje automatycznie zakończone.

Przykłady

Poniższy prosty przykład kod wykorzystuje pthread_create () tworzy pięć tematów każde wyjście "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);
}

Użyj -lpthread biblioteki skompilowany następujący program:

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

Teraz, realizacja programu przyniesie następujące wyniki:

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

Poniższy prosty przykład kod wykorzystuje pthread_create () tworzy pięć wątków, a otrzymasz parametry przychodzących. Każdy wątek drukuje "Hello!" W3big wiadomość i wysyła otrzymane parametry, a następnie zadzwonić pthread_exit () kończy wątek.

//文件名: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);
}

Teraz skompilować i uruchomić program przyniesie następujące wyniki:

$ 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

Przekazać parametry do wątku

Ten przykład pokazuje, w jaki sposób przekazać wiele parametrów struktury. można przekazać dowolny typ danych w zwrotnego gwintu, ponieważ wskazuje próżni, jak to przedstawiono w następujących przykładach:

#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);
}

Gdy powyższy kod jest kompilowany i wykonany, że daje następujące wyniki:

$ 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

Łączenie i rozdzielanie nici

Możemy użyć następujących funkcji, aby połączyć dwa lub oddzielne wątki:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join () podprogram utrudniają programu wywołującego aż określona ThreadID gwint kończy. Podczas tworzenia wątku, to atrybut określa, czy jest on podłączony (PŁYCIE) lub odłączalny (wolnostojący). Określić tylko utworzyć gwint, który może być podłączony może zostać połączony. Jeśli gwint jest tworzony jest określony jako rozłączne, to nigdy nie może być podłączony.

Ten przykład pokazuje, jak używać pthread_join funkcji () czekać na gwincie zakończenia.

#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);
}

Gdy powyższy kod jest kompilowany i wykonany, że daje następujące wyniki:

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.