Multithreading is a special form of multitasking that allows a computer to run two or more programs at the same time. In general, two types of multitasking: process based and thread based.
Process-based multitasking is the concurrent execution of a program.
Multitasking of threads is concurrent execution of fragments of the same program.
A multithreaded program contains two or more parts that can be run concurrently. Each part of such a program is called a thread, and each thread defines a separate execution path.
C + + does not contain any built-in support for multithreaded applications. Instead, it relies entirely on the operating system to provide this functionality.
This tutorial assumes that you are using a Linux operating system, and we want to use POSIX to write multithreaded C + + programs. The APIs provided by POSIX Threads or Pthreads can be available on a variety of Unix-like POSIX systems, such as FreeBSD, NetBSD, Gnu/linux, Mac OS X, and Solaris. Creating Threads
The following program, we can use it to create a POSIX thread:
#include <pthread.h>pthread_create (thread, attr, Start_routine, Arg)
Here, Pthread_create creates a new thread and makes it executable. Here is a description of the parameter: parameter description
Parameters |
Description |
Thread |
Point to the thread identifier pointer. |
attr |
An opaque Property object that can be used to set the thread properties. You can specify a thread Property object, or you can use the default value NULL. |
Start_routine |
The thread runs the start address of the function, which is executed once the thread is created. |
Arg |
The parameters of the run function. It must be passed by casting the reference as a pointer to a void type. If no arguments are passed, NULL is used. |
When you create a line Cheng, the function returns 0, and if the return value is not 0, the creation thread fails. terminating a thread
Using the following program, we can use it to terminate a POSIX thread:
#include <pthread.h>pthread_exit (status)
Here, Pthread_exit is used to explicitly exit a thread. Typically, the Pthread_exit () function is invoked when a thread completes work without continuing to exist.
If main () is terminated before the thread it creates and exits through Pthread_exit (), the other threads will continue to execute. Otherwise, they are automatically terminated at the end of Main ().
Instance:
The following simple instance code creates 5 threads using the Pthread_create () function, and each thread outputs "Hello runoob." ":
#include <iostream>// required header file is #include <pthread.h>using namespace std;#. define num_threads 5// The running function of a thread, the function returns a function pointer that is easy to follow as a parameter void* say_hello (void* args) { cout << "Hello runoob. " << endl;} Int main () { // defines a thread's id variable, and multiple variables use an array pthread_ T tids[num_threads]; for (int i = 0; i < num_ Threads; ++i) The { //parameter is: The thread ID created, Thread parameters, called functions, incoming function arguments int ret = pthread_create ( &tids[i], null, say_hello, null); if ( ret != 0) { cout << "Pthread_create error: error_code=" << ret << endl; } } //and so on, after each thread exits, the process ends, Otherwise the process is forced to end, and the thread may not be responding; pthread_exit (NULL);}
Use the-lpthread library to compile the following program:
$ g++ Test.cpp-lpthread-o TEST.O
Now, executing the program will produce the following results:
$./test.ohello Runoob. Hello Runoob. Hello Runoob. Hello Runoob. Hello Runoob.
The following simple instance code creates 5 threads using the Pthread_create () function and receives incoming arguments. Each thread prints a "Hello runoob!" message and outputs the received parameters, and then calls Pthread_exit () to terminate the thread.
FileName:test.cpp#include <iostream> #include <cstdlib> #include <pthread.h>using namespace std; #define num_threads 5void *printhello (void *threadid) { // The incoming parameter to a cast, from an untyped pointer to an integer pointer, and then read the int tid = * ((int*) threadid); cout << "hello runoob! thread ID, " << tid << endl; pthread_exit (NULL);} int main () { pthread_t threads[num_threads]; int indexes [num_threads];// uses an array to hold the value of I int rc; int i; for ( i=0; i < NUM_THREADS; i++ ) { cout << "Main () : create thread, " << i << endl; indexes[i] = i; //first saves the value of I // must be cast to void* type when passed in, that is, no type pointer rc = pthread_create (&threads[i], NULL, PrintHello, (void *) & (Indexes[i]); if (RC) { cout << "Error: Unable to create thread," << rc << endl; exit ( -1); } } pthread_exit (NULL);}
Compiling and executing the program now produces the following results:
$ g++ test.cpp-lpthread-o test.o$./test.omain (): Create Thread, 0main (): Create Thread, 1main (): Create Thread, 2main (): Create Thread, 3main (): Create Thread, 4Hello runoob! Thread ID, 4Hello runoob! Thread ID, 3Hello runoob! Thread ID, 2Hello runoob! Thread ID, 1Hello runoob! Thread ID, 0
passing parameters to a thread
This example demonstrates how to pass multiple parameters through a struct. You can pass any data type in a thread callback because it points to void, as shown in the following example:
#include <iostream> #include <cstdlib> #include <pthread.h>using namespace std; #define num_threads 5struct 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]); // Incoming to parameter must be strongly converted to void* type, that is, no type pointer if (RC) { cout << "Error:unable to create thread," << Rc << endl; exit ( -1); } } pthread_exit (NULL);}
When the above code is compiled and executed, it produces the following results:
$ g++-wno-write-strings test.cpp-lpthread-o test.o$./test.omain (): Creating Thread, 0main (): Creating Thread, 1main ( ): Creating Thread, 2main (): Creating Thread, 3main (): Creating Thread, 4Thread id:3 message:this is Messagethread Id:2 Message:this is Messagethread id:0 message:this are messagethread id:1 message:this is messagethread ID: 4 Message:this is message
Connecting and detaching Threads
We can use the following two functions to connect or detach a thread:
Pthread_join (ThreadID, status) Pthread_detach (ThreadID)
The Pthread_join () subroutine blocks the calling program until the specified ThreadID thread terminates. When a thread is created, one of its properties defines whether it is a joinable or separable (detached). Only threads that are defined as connected can be connected when they are created. If a thread is created as separable, it can never be connected.
This example demonstrates how to use the Pthread_join () function to wait for the thread to complete.
#include <iostream> #include <cstdlib> #include <pthread.h> #include < unistd.h>using namespace std; #define num_threads 5void * 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; // Initialize and set the thread to be connected (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," &NBSP;<<&NBSP;RC << endl; exit ( -1); } } // Delete attributes and wait for other threads to 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 << "&NBSP;&NBSP;EXITING&NBSP;WITH&NBSP;STATUS&NBSP;:" << status << endl; } cout << "main: program exiting." << endl; pthread_exit (NULL);}
When the above code is compiled and executed, it produces the following results:
Main () : creating thread, 0main () : creating thread, 1main () : creating thread, 2main () : creating thread, 3main () : creating thread, 4sleeping 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 :0main: completed thread id :1 exiting with status :0main: completed thread id :2 exiting with status :0main: completed thread id :3 exiting with status :0main: completed thread id :4 exiting with status : 0main: program exiting.
implementation of mutual exclusion lock
Mutex is a mechanism to implement thread synchronization, as long as locking the resource before and after the critical section can block the access of other processes.
#include <iostream> #include <pthread.h>using namespace std; #define num_ threads 5int sum = 0; //defines global variables so that all threads are written at the same time, which requires locking mechanisms pthread_mutex_t sum_mutex; Mutual-exclusion lock Void* say_hello ( void* args ) { cout << "Hello in thread " << * (( int * ) args) << endl; pthread_mutex_lock ( &sum_mutex ) //first Lock, then modify the value of sum, lock is occupied to block until the lock and then modify sum; cout << "before sum is " << sum << " in thread " << * ( ( int* ) args ) < < endl; sum += * ( ( int* ) args ); cout << "after sum is " << sum << " in thread " << * ( ( int* ) args ) << endl; Pthread_mutex_unlock ( &sum_mutex ) //release locks for other threads to use pthread_exit ( 0 ); Int main () { pthread_t tids[num_threads]; int indexes[num_threads]; pthread_attr_t attr; //thread property structure, parameters added when creating Threads pthread_attr_init ( &attr ) //initialization pthread_attr_ Setdetachstate ( &attr, PTHREAD_CREATE_JOINABLE ); //is set you want to specify the thread attribute parameters, This parameter indicates that this thread can join joins, the Join function means that the main program can wait for the end of the thread to do something, implement the main program and thread synchronization function pthread_mutex_init ( &sum_mutex, NULL ); //locks are initialized for ( int i = 0; i < NUM_THREADS; ++i ) { indexes[i] = i;&Nbsp; &nb