Article catalog
Threads, sometimes called lightweight processes, are the smallest unit of program execution.
C++11 thread
#include <thread> void task(int i) { cout << "task:" << i << endl; } thread t1(task,100); //Wait for the thread to end before continuing t1.join();
POSIX Threads
POSIX portable operating system interface, which defines the interface standard that the operating system should provide for the application
Use configuration on Windows: download
cmake_minimum_required (VERSION 3.8) include_directories("XXX/pthreads-w32-2-9-1-release/Pre-built.2/include") #Set variable to x64 or x86 if(CMAKE_CL_64) set(platform x64) else() set(platform x86) endif() link_directories("XXX/pthreads-w32-2-9-1-release/Pre-built.2/lib/${platform}") #If "timespec": "struct" type redefinition setting appears set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_STRUCT_TIMESPEC") # Add a source to the executable for this project. add_executable (lsn6example "lsn6_example.cpp" "lsn6_example.h") target_link_libraries(lsn6example pthreadVC2)
32-bit copy pthreadVC2.dll to windows/syswow64 directory
64 bit copy pthreadVC2.dll to windows/system32 directory
#include <pthread.h> void *pthreadTask(void* args) { int* i = static_cast<int*>(args); cout << "posix thread :" << *i << endl; return 0; } pthread_t pid; int pi = 100; pthread_create(&pid, 0, pthreadTask, &pi); //Wait for the end of the thread pthread_join(pid,0);
Thread properties
Thread has properties, using pthread_attr_t represents
pthread_attr_t attr; //Initializes the default values for all properties of threads supported by the operating system implementation in attr pthread_attr_init(&attr); pthread_attr_destroy(&attr);
Detach thread
Thread creation is non detached by default, when pthread_ When the join() function returns, the thread created is terminated and the system resources occupied are released
Detached thread cannot be waited by other threads, pthread_ The join is invalid. The thread plays its own.
//Set whether it is a detached thread //PTHREAD_CREATE_DETACHED //PTHREAD_CREATE_JOINABLE non separation pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
Scheduling strategy and priority
Windows cannot set successfully
//Set scheduling policy //Return 0 to set successfully pthread_attr_setschedpolicy(&attr, SCHED_FIFO); // SCHED_FIFO // Real time scheduling strategy: first come first serve runs all the time once cpu is occupied. Run until a higher priority task arrives or abandons itself. // SCHED_RR // Real time scheduling strategy: the time rotation system allocates a time period to execute this thread within the time period //set priority //Get the minimum and maximum priority of the corresponding policy int max = sched_get_priority_max(SCHED_FIFO); int min = sched_get_priority_min(SCHED_FIFO); sched_param param; param.sched_priority = max; pthread_attr_setschedparam(&attr, ¶m);
Thread synchronization
When multiple threads read and write the same shared resource at the same time, conflicts may occur. It is necessary to introduce the thread "synchronization" mechanism, that is, each thread operates the shared resources orderly.
#include <pthread.h> using namespace std; queue<int> q; void *pop(void* args) { //Multithreading security problems caused by unsynchronized threads // There will be repeated data fetches and exceptions if (!q.empty()) { printf("Retrieve data:%d\n", q.front()); q.pop(); } else { printf("No data\n"); } return 0; } int main() { for (size_t i = 0; i < 5; i++) { q.push(i); } pthread_t pid[10]; for (size_t i = 0; i < 10; i++) { pthread_create(&pid[i], 0, pop, &q); } system("pause"); return 0; }
Join mutex
queue<int> q; pthread_mutex_t mutex; void *pop(void* args) { // lock pthread_mutex_lock(&mutex); if (!q.empty()) { printf("Retrieve data:%d\n", q.front()); q.pop(); } else { printf("No data\n"); } // discharge pthread_mutex_unlock(&mutex); return 0; } int main() { //Initialize mutex pthread_mutex_init(&mutex, 0); for (size_t i = 0; i < 5; i++) { q.push(i); } pthread_t pid[10]; for (size_t i = 0; i < 10; i++) { pthread_create(&pid[i], 0, pop, &q); } //Release required for (size_t i = 0; i < 10; i++) { pthread_join(pid[i], 0); } pthread_mutex_destroy(&mutex); system("pause"); return 0; }
Conditional variable
Condition variable is a mechanism for synchronization between threads, which mainly includes two actions: one thread waits for "condition of condition variable is established" and suspends; the other thread makes "condition is established" so as to wake up the suspended thread
```cpp template <class T> class SafeQueue { public: SafeQueue() { pthread_mutex_init(&mutex,0); } ~SafeQueue() { pthread_mutex_destory(&mutex); } void enqueue(T t) { pthread_mutex_lock(&mutex); q.push(t); pthread_mutex_unlock(&mutex); } int dequeue(T& t) { pthread_mutex_lock(&mutex); if (!q.empty()) { t = q.front(); q.pop(); pthread_mutex_unlock(&mutex); return 1; } pthread_mutex_unlock(&mutex); return 0; } private: queue<T> q; pthread_mutex_t mutex; };
> The above template class stores data T,And use mutually exclusive lock to ensure queue Is thread safe. This is a production/Consumption mode. > If you are taking out data, queue If it is empty, wait until the next time enqueue Add data. > This is a typical production/consumption pattern, Add condition variable to make“ dequeue" Pending,Until it wakes up somewhere else ```cpp #pragma once #include <queue> using namespace std; template <class T> class SafeQueue { public: SafeQueue() { pthread_mutex_init(&mutex,0); pthread_cond_init(&cond, 0); } ~SafeQueue() { pthread_mutex_destory(&mutex); pthread_cond_destory(&cond); } void enqueue(T t) { pthread_mutex_lock(&mutex); q.push(t); //Signal to suspend thread //Wake up a thread by the system //pthread_cond_signal(&cond); // When the broadcast corresponds to multiple consumers, multiple threads wait to wake up all pthread_cond_broadcast(&cond); pthread_mutex_unlock(&mutex); } int dequeue(T& t) { pthread_mutex_lock(&mutex); //May be awakened unexpectedly, so while loop while (q.empty()) { pthread_cond_wait(&cond, &mutex); } t = q.front(); q.pop(); pthread_mutex_unlock(&mutex); return 1; } private: queue<T> q; pthread_mutex_t mutex; pthread_cond_t cond; };
#include "lsn6_example.h" #include <thread> #include <pthread.h> using namespace std; #include "safe_queue.h" SafeQueue<int> q; void *get(void* args) { while (1) { int i; q.dequeue(i); cout << "consumption:"<< i << endl; } return 0; } void *put(void* args) { while (1) { int i; cin >> i; q.enqueue(i); } return 0; } int main() { pthread_t pid1, pid2; pthread_create(&pid1, 0, get, &q); pthread_create(&pid2, 0, put, &q); pthread_join(pid2,0); system("pause"); return 0; }