Multithreaded Concurrent Programming for C++11

Keywords: Programming Ubuntu

Multithreaded concurrent programming for C++11 (2)

The epidemic has reached 3w+, and we hope to end it soon.
Based on the threading concepts learned in the previous section, I started to learn more about multi-threaded programming in the new standard of C++11. C++11 introduced five header files: atomic, thread, mutex, condition_variable, future.Includes related classes such as mutexes, conditional variables, synchronous threads and asynchronous threads. This section mainly records the threadheader files.

  1. Thread creation std::thread
    There are three main constructors for std:: threads: a parameterless constructor, an initialization constructor, and a moving constructor.Write a code to lift a chestnut:
#include <iostream>
#include <thread>
#include <unistd.h>

using namespace std;
void myFunc1()
{	
	cout << "hello comedy" << endl;
}
void myFunc2(int i)
{
	cout << "hello comedy" << i << endl;
}
int main(int argc, char *argv[])
{
	int i = 99;
	thread t1(myFunc1);
	thread t2(myFunc2,i);
	thread t3(myFunc3,i);
	thread t4(move(t3));

	sleep(1);
	cout << "the main thread is end;" << endl;
	
	return 0;
}

Sleep (1) lets the main thread sleep for one second, and the child threads have enough time to run, because whether the process finishes execution depends on whether the main thread finishes execution.If the main thread ends but the child thread does not have time to execute, it will be forced to end by the operating system.

  1. Blocking join() of thread

A function join() is provided in the threadclass; it represents the join and turn of a thread, which is equivalent to sleep (n), and is used to block the main thread until the child thread finishes execution.Usage example:

#include <iostream>
#include <thread>

using namespace std;

void myFunc(char *str)
{
	cout << "hello " << str << endl;
}

int main(int argc, char *argv[])
{
	char str[] = "comedy!";
	thread t1(myFunc , str);
	t1.join();
	cout << "the main thread is endl;" << endl;
	return 0;
}

A good program is that the main thread waits for the child thread to finish executing before it finishes itself.However, the threadclass provides a member function detach() that allows the child and main threads to run their own without waiting.

  1. Thread detach()
    Thread detachment, where a child thread object calls the detach member function, causes the child thread to lose its association with the main thread, when the main thread ends and the child thread does not end, and the child thread is taken over by the background C++ runtime. The detached thread is the daemon thread, or a cache cleanup task, or a file monitoring task.Here's an example to illustrate a problem.
    Write c++ program files in the specified file directory of the Ubuntu system.
#include <iostream>
#include <thread>

using namespace std;

class myTest
{
	public:
		int parameter;
		myTest(int i): parameter(i){}
		void operator()()
		{
			cout << "my thread is createed" << endl;
			cout << "my parameter is :" << parameter << endl;
			//do something.....
			cout << "my thread is end" << endl;
			
		}
};

int main(int argc, char *argv[])
{
	int x = 99;
	myTest test(x);
	thread mythread(test);
	mythread.detach();
	
	cout << "the main thread is end " << endl;
	return 0;
	
}

Then compile the link library g++ 8.5.cpp-o 8.5-pthread-std=c++ 11 by command execution
And executed by command. /8.5 The result is shown in the figure:

As you can see from the diagram, the main thread terminates very early, but the child thread is still executing, but the end of the main thread destroys the test object, where does the child thread come from?By modifying the case code: add class constructors and copy constructors and fictitious functions.

#include <iostream>
#include <thread>

using namespace std;

class myTest
{
	public:
		int parameter;
		myTest(int i): parameter(i)
		{
			cout << "myTest's createFunction is running" << endl;
		}
		myTest(const myTest &test): parameter(test.parameter)
		{
			cout << "myTest's copyFunction is running" << endl;
		}
	
		~myTest()
		{
			cout << "myTest's removeFunction is running" << endl;
		}
		void operator()()
		{
			cout << "my thread is createed" << endl;
			cout << "my parameter is :" << parameter << endl;
			//do something.....
			cout << "my thread is end" << endl;
			
		}
};

int main(int argc, char *argv[])
{
	int x = 99;
	myTest test(x);
	thread mythread(test);
	mythread.detach();
	
	cout << "the main thread is end " << endl;
	return 0;
	
}

The results are shown in the diagram:


The result shows that the object of the first destructor is actually assigned to the thread, the object of the main thread that executes the main thread is destructed, and the destructor is called when the child thread executes.

The next section continues with the thread passing section.

Two original articles were published, 0 were praised, and 88 were visited
Private letter follow

Posted by dt_gry on Fri, 07 Feb 2020 22:36:05 -0800