2021/10/1C++11 concurrency and multithreading note thread start and end, create multithreading method, join and detach

Keywords: Multithreading

1, The example demonstrates the beginning of thread operation

  • When the program runs, a process is generated, and the main thread to which the process belongs starts to run automatically; When the main thread returns from the main () function, the whole process is completed
  • The main thread starts to execute from main (), so the thread created by ourselves also needs to run from a function (initial function). Once the function runs, the thread also ends
  • The flag of whether the whole process has been executed is: whether the main thread has been executed. If the main thread has been executed, it means that the whole process has been executed. At this time, if other sub threads have not been executed, they will also be forcibly terminated [there are exceptions to this article, which will be explained later]

Create a thread:

  1. Include header file thread
  2. Write initial function
  3. Create thread in main

It must be understood that two threads are running, which is equivalent to two lines walking at the same time in the whole program. Even if one is blocked, the other can run

1.1 thread
(1) A thread is created, and the starting point (entry) of thread execution is myPrint;
(2) Execution thread
1.2 join()
Block the main thread and wait for myPrint to finish executing. When myPrint finishes executing, join() will finish executing and the main thread will continue to execute; Join means confluence, child thread and main thread round
1.3 detach()
In traditional multithreaded programs, the main thread waits for the execution of the child thread, and then exits at last.
Detach: detach. The main thread will no longer merge with the child thread and will no longer wait for the child thread
After detach, the child thread loses its association with the main thread and resides in the background, which is taken over by the C + + runtime library
Once detach reaches the background, you cannot join back, otherwise the system will call an exception
1.4 joinable()
Determine whether you can successfully use join() or detach()
If true is returned, it proves that join() or detach() can be called
If false is returned, it proves that join() or detach() has been called, and neither join() nor detach() can be called again

#include <iostream>
#include <thread>
using namespace std;

void myPrint()
{
	cout << "My thread starts running" << endl;
	//-------------
	//-------------
	cout << "My thread is running" << endl;
	return;
}

int main()
{
	//(1) A thread is created, and the starting point (entry) of thread execution is myPrint; (2) Execution thread
	thread myThread(myPrint);

	//(2) Block the main thread and wait for myPrint to finish executing. When myPrint finishes executing, join() finishes executing and the main thread continues to execute
	//join means confluence, child thread and main thread round
	myThread.join();

	//Set the breakpoint to see the main thread waiting for the child thread
	//F11 statement by statement is to execute one line of statement at a time. If a function call is encountered, it will enter the function
	//F10 process by process. When a function is encountered, it does not enter the function, and the function call is executed as a statement

	//(3) In traditional multithreaded programs, the main thread has to wait for the sub thread to finish executing, and then it can execute downward
	//Detach: detach. The main thread will no longer merge with the child thread and will no longer wait for the child thread
	//After detach, the child thread loses its association with the main thread and resides in the background, which is taken over by the C + + runtime library
	//myThread.detach();

	//(4)joinable() determines whether join() or detach() can be used successfully
	//If true is returned, it proves that join() or detach() can be called
	//If false is returned, it proves that join() or detach() has been called, and neither join() nor detach() can be called again
	if (myThread.joinable())
	{
		cout << "Can call can call join()perhaps detach()" << endl;
	}
	else
	{
		cout << "Cannot call can call join()perhaps detach()" << endl;
	}
	
	cout << "Hello World!" << endl;
	return 0;
}

Important additions:
The thread class parameter is a callable object.
A group of executable statements are called callable objects. Callable objects in c + + can be functions, function pointers, lambda expressions, objects created by bind, or class objects that overload function call operators.

2, Other ways to create threads
(1) Create a class, write parenthesis overloaded functions, initialize an object of this class, and take this object as the thread entry address

class Ta
{
public:
	void operator()() //Cannot take parameter
	{
		cout << "My thread starts running" << endl;
		//-------------
		//-------------
		cout << "My thread is running" << endl;
	}
};

//In the main function:
	Ta ta;
	thread myThread(ta);
	myThread.join();

One question is, once detach() is called, the main thread execution ends. Is the TA object I use here still there? This object is actually copied to the thread. After executing the main thread, TA will be destroyed, but the copied TA object still exists.
Therefore, as long as there is no reference or pointer in the TA class object, there will be no problem;

(2) lambda expression creation thread

//In the main function
auto lambdaThread = [] {
		cout << "My thread started executing" << endl;
		//-------------
		//-------------
		cout << "My thread started executing" << endl;
	};

	thread myThread(lambdaThread);
	myThread.join();

(3) Take a function in a class as the entry address of the thread

class Data_
{
public:
    void GetMsg(){}
    void SaveMsh(){}
};
//In the main function
    Data_ s;
    //The first & means addressing, and the second & means reference, which is equivalent to std::ref(s)
    //Thread oneobj (& data_:: savemsh, s) can also pass values
    //In other constructors & obj does not represent a reference and will be treated as an address
    //Calling method: object member function address, class instance, [member function parameter]
	//The second parameter can pass either object s or reference std::ref(s) or & S
	//Passing s will call the copy constructor to generate a new object in the child thread
	//Pass &, the original object is still used in the child thread, so you can't detach, because the object will be released after the main thread runs
    thread oneobj(&Data_::SaveMsh,&s);
    thread twoobj(&Data_::GetMsg,&s);
    oneobj.join();
    twoobj.join();

Posted by rondog on Sat, 02 Oct 2021 15:04:24 -0700