Latest web development tutorials

C ++ Multithreading

Multithreading adalah bentuk khusus dari multi-tasking, multi-tasking memungkinkan membiarkan komputer berjalan dua atau lebih program. Secara umum, dua jenis multitasking: proses berbasis dan benang berbasis.

  • Program multitasking berbasis proses dijalankan secara bersamaan.
  • multitasking berbasis benang pengolahan adalah pelaksanaan bersamaan dari fragmen program yang sama.

Program multithreaded mengandung dua atau lebih bagian yang dapat dijalankan secara bersamaan. program tersebut untuk masing-masing bagian disebut thread, setiap thread mendefinisikan jalan terpisah eksekusi.

C ++ tidak termasuk built-in mendukung untuk aplikasi multi-threaded. Sebaliknya, itu benar-benar tergantung pada sistem operasi untuk menyediakan fungsi ini.

Tutorial ini mengasumsikan bahwa Anda menggunakan sistem operasi Linux, kita ingin menggunakan POSIX menulis C ++ Program multithreaded. API POSIX Threads atau Pthreads dapat diberikan pada beberapa jenis sistem Unix POSIX tersedia, seperti FreeBSD, NetBSD, GNU / Linux, Mac OS X dan Solaris.

Membuat sebuah thread

Program berikut, kita dapat menggunakannya untuk membuat POSIX thread:

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

Di sini, pthread_create menciptakan thread baru dan membuatnya executable.Berikut ini adalah deskripsi dari parameter:

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

Ketika thread dibuat sukses, fungsi mengembalikan 0, jika nilai kembali dari 0 menunjukkan bahwa gagal untuk membuat thread.

Hentikan benang

Gunakan prosedur berikut, kita dapat menggunakannya untuk mengakhiri POSIX thread:

#include <pthread.h>
pthread_exit (status) 

Di sini, pthread_exit digunakan untuk secara eksplisit keluar benang.Dalam keadaan normal, pthread_exit () fungsi disebut ketika pekerjaan dilakukan tanpa harus terus ada setelah benang.

Jika main () sebelum akhir benang yang dibuat, dan keluar melalui pthread_exit (), maka benang lainnya akan terus mengeksekusi. Jika tidak, mereka akan berada di main () pada akhir secara otomatis dihentikan.

contoh

Contoh berikut kode sederhana menggunakan pthread_create () fungsi menciptakan lima benang, setiap output "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);
}

Menggunakan perpustakaan -lpthread disusun program berikut:

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

Sekarang, pelaksanaan program akan menghasilkan hasil sebagai berikut:

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

Contoh berikut kode sederhana menggunakan pthread_create () fungsi menciptakan lima benang, dan menerima parameter yang masuk. Setiap thread mencetak "Hello w3big!" Pesan, dan output parameter yang diterima, dan kemudian memanggil pthread_exit () berakhir benang.

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

Sekarang mengkompilasi dan mengeksekusi program akan menghasilkan hasil sebagai berikut:

$ 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

Melewatkan parameter ke Thread

Contoh ini menunjukkan bagaimana untuk melewati beberapa struktur parameter. Anda dapat melewati semua jenis data dalam callback benang, karena menunjuk ke kekosongan, seperti yang ditunjukkan dalam contoh berikut:

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

Ketika kode di atas dikompilasi dan dijalankan, menghasilkan hasil sebagai berikut:

$ 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

Menghubungkan dan memisahkan benang

Kita dapat menggunakan dua fungsi berikut untuk menghubungkan atau benang yang terpisah:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join () subroutine menghambat program menelepon sampai benang threadid ditentukan berakhir. Ketika Anda membuat sebuah thread, itu atribut mendefinisikan apakah itu terhubung (joinable) atau dilepas (terpisah). Mendefinisikan hanya membuat thread yang dapat terhubung dapat dihubungkan. Jika thread dibuat didefinisikan sebagai dipisahkan, tidak pernah dapat terhubung.

Contoh ini menunjukkan bagaimana menggunakan pthread_join () fungsi untuk menunggu thread selesai.

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

Ketika kode di atas dikompilasi dan dijalankan, menghasilkan hasil sebagai berikut:

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.