C++11 Multithreading: Atomic operations std::automatic - for variables shared between multiple threads.

Series Article Directory



foreword

(1) Basic concept and usage of atomic operation std::automic.
(2) Precautions for use.


1. The basic concept of std::automic

std::atomicto represent atomic operations and std::automicis a class template . In fact, std::atomic is used to encapsulate a certain type of value.

  • Ordinary variables:

Multiple concurrent accesses may cause data competition, resulting in the operation process not being performed in the correct order;

  • Atomic variable:

Ensure that operations on shared variables will not be interfered by operations of other threads during execution, avoiding race conditions and deadlocks.

1.1 Introducing examples of the concept of atomic operations

Mutex: Protect shared data in multi-threaded programming: lock first, operate shared data, unlock

有两个线程,对一个变量进行操作,这个线程读该变量值,另一个线程往这个变量中写值。
int atomvalue = 5//读线程A
int tmpvalue = atomvalue;
//这里这个atomvalue代表的是多个线程之间共享的变量;
//写线程B
atomvalue = 6;

1.2 Assembling code;
you can understand atomic operations as a multi-threaded concurrent programming method that does not require mutex locking (lock-free) technology

  • Atomic operation: Program execution fragments that will not be interrupted in multithreading; atomic operations are more efficient than mutexes.
  • The locking of the mutex is generally aimed at a code segment (a few lines of code), while the atomic operation is generally aimed at a variable, not a code segment;
  • Atomic operation: generally refers to "indivisible operation"; that is to say, the operation state is either completed or not completed, and it is impossible to have a half-completed state;

2. Function members

store replaces the value of an atomic object with a nonatomic parameter
load Get the value of the atomic object
exchange swaps the values ​​of two atomic objects
wait Block the thread until notified and the atomic value changes
notify_one Notify that at least one thread is waiting on the atomic object
notify_all Notifies all blocked threads to wait on the atomic object

3. Use steps

1. Code Case 1

The code is as follows (example):
Basic usage.

#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#include <vector>
#include <string>
#include <map>
#include <thread>
#include <list>
#include <mutex>
#include <future>
//int g_mycout = 0; //定义一个全局变量
std::atomic<int> g_mycout = 0; //我们封装了一个类型为int的对象(值);我们可以像操作一个int类型变量一样来操作这个g_mycout

//std::mutex g_my_mutex; //互斥量

void mythread03() //线程入口函数
{
    
    
	for (int i = 0; i < 100000; i++)
	{
    
    
		//g_my_mutex.lock();
		//7秒钟实现了2000万次的加锁和解锁;
		//g_mycout++;
		//...
		//...
		//g_my_mutex.unlock();
		
		g_mycout++;
		//g_mycout = gmycout + 1;  //会导致计数不准确
		
		//cout <<""
		//对应的操作是原子操作(不会被打断)
	}
	
	
	return;
}

int main()
{
    
    
	//三:原子操作std::automic
	//(3.1)原子操作概念引出范例
	//互斥量:多线程编程中 保护共享数据:先锁,操作共享数据,开锁
	//有两个线程,对一个变量进行操作,这个线程读该变量值,另一个线程往这个变量中写值。
	//int atomvalue = 5;
	读线程A
	//int tmpvalue = atomvalue;
	//这里这个atomvalue代表的是多个线程之间共享的变量;
	写线程B
	//atomvalue = 6;
	//汇编代码的话;

	//大家可以把原子操作理解成一种:不需要用到互斥量加锁(无锁)技术的多线程并发编程方式
	//原子操作:在多线程中 不会被打断的 程序执行片段;原子操作,比互斥量效率上更胜一筹。
	//互斥量的加锁一般是针对一个代码段(几行代码),而原子操作针对的一般是一个变量,而不是一个代码段;

	//原子操作:一般都是指“不可分割的操作”;也就是说这种操作状态要么是完成的,要么是没完成的,不可能出现半完成状态;
	//std::atomic来代表原子操作,std::automic是个类模板。其实std::atomic这个东西是用来封装某个类型的值的;
	//(3.2)基本的std::atomic

	std::thread myobj1(mythread03);
	std::thread myobj2(mythread03);
	cout << "线程开始!" << g_mycout<< endl;
	myobj1.join();
	cout << "thread_myobj1 end!" << g_mycout << endl;
	myobj2.join();
	cout << "thread_myobj2 end!" << g_mycout << endl;

	cout << "两个线程执行完毕,最终的g_mycout的结果是:" << g_mycout << endl;

	return 0;
}

Run the screenshot:
insert image description here

Note: If
the general atomic operation is here, it is supported for ++, –, +=, &=, |=, ^=. Others may not be supported.


2. Code case 2

Use std::automic variable to control, the end of multiple threads
can also be used to count, count, and calculate the sending and receiving of data packets.

std::atomic<bool> g_ifend = false; //线程退出标记,这里是原子曹组,防止读和写乱套;

void mythread04()
{
    
    
	std::chrono::milliseconds dura(1000);
	//1秒钟
	while (g_ifend == false)
	{
    
    
		//系统没要求线程退出,所以本线程可以干自己想干的事情
		cout << "thread id = " << std::this_thread::get_id() << " 运行中..." << endl;
		std::this_thread::sleep_for(dura);
	}
	cout << "thread id = " << std::this_thread::get_id() << " 运行中结束..." << endl;
	return;
}

int main()
{
    
    
	//心得,一般用于计数或者统计(累计发送出去了多少个数据包,累计接受到了多个数据包;)

	std::thread myobj1(mythread04);
	std::thread myobj2(mythread04);
	std::chrono::milliseconds dura(5000);
	//5秒钟
	std::this_thread::sleep_for(dura);
	g_ifend = true;
	//对原子对象的写操作,让线程自行运行结果;
	myobj1.join();
	myobj2.join();
	cout << "程序执行完毕,退出" << endl;

	return 0;
}

Run the screenshot:
insert image description here

Summarize

  • Understand the basic concepts and usage of std::automic;
  • Understand the difference between std::automic and mutex ;
  • What are atomic operations?
  • Use std::automatic to control the termination of multiple threads.

Guess you like

Origin blog.csdn.net/weixin_55491446/article/details/130117072