C++中的原子操作
Atomic Operations in C++
我有一组C++函数:
funcB(){};
funcC(){};
funcA()
{
funcB();
funcC();
}
现在我想使funcA
原子化,即funcA
内部的funcB
和funcC
调用应该原子化执行。有什么办法做到这一点吗?
实现这一点的一种方法是使用新的(C++11)特性std::mutex
和std::lock_guard
。
对于每个受保护的资源,实例化一个全局std::mutex
;然后,每个线程根据需要通过创建std::lock_guard
:来锁定该互斥对象
#include <thread>
#include <iostream>
#include <mutex>
#include <vector>
// A single mutex, shared by all threads. It is initialized
// into the "unlocked" state
std::mutex m;
void funcB() {
std::cout << "Hello ";
}
void funcC() {
std::cout << "World." << std::endl;
}
void funcA(int i) {
// The creation of lock_guard locks the mutex
// for the lifetime of the lock_guard
std::lock_guard<std::mutex> l(m);
// Now only a single thread can run this code
std::cout << i << ": ";
funcB();
funcC();
// As we exit this scope, the lock_guard is destroyed,
// the mutex is unlocked, and another thread is allowed to run
}
int main () {
std::vector<std::thread> vt;
// Create and launch a bunch of threads
for(int i =0; i < 10; i++)
vt.push_back(std::thread(funcA, i));
// Wait for all of them to complete
for(auto& t : vt)
t.join();
}
注:
- 在您的示例中,一些与
funcA
无关的代码可以调用funcB
或funcC
,而不遵守funcA
设置的锁 - 根据程序的结构,您可能希望以不同的方式管理互斥体的生存期。例如,它可能希望成为包含
funcA
的类的类成员
一般来说,NO。原子操作的定义非常精确。您想要的是一个信号量或互斥量。
如果您使用GCC 4.7,则可以使用新的事务内存功能来执行以下操作:
事务内存旨在简化使用线程的编程,特别是使用事务同步访问几个线程之间共享的数据。与数据库一样,事务是一个工作单元,它要么完整完成,要么根本没有效果(即事务以原子方式执行)。此外,事务是相互隔离的,这样每个事务都可以看到一致的内存视图。
目前,C++和C中只支持事务语句、事务表达式和函数事务形式的事务。在下面的例子中,a和b都将被读取,差异将被写入c,所有这些都是原子性的,并与其他事务隔离:
__transaction_atomic { c = a - b; }
因此,另一个线程可以使用以下代码同时更新b,而不会导致c保持负值(并且不必使用其他同步结构,如锁或c++11原子):
__transaction_atomic { if (a > b) b++; }
事务的精确语义是根据C++11/C1X内存模型定义的(请参阅下面的规范链接)。大致来说,事务提供的同步保证类似于使用单个全局锁作为所有事务的保护时所保证的同步保证。请注意,与C/C++中的其他同步结构一样,事务依赖于无数据竞赛的程序(例如,与对同一内存位置的事务读取同时进行的非事务写入是数据竞赛)。
更多信息:http://gcc.gnu.org/wiki/TransactionalMemory
- 对OpenMP reduction子句中的变量执行原子操作
- C++:将值赋值给原始数据类型(例如布尔值)是原子操作吗?
- 标记为 std::memory_order_seq_cst 的单个原子操作是否会在所有位置触发顺序一致性?
- 对单个变量的原子操作
- 对于 CPU 无法原子操作的类型,std::atomic 有什么意义?
- 为什么互斥对象与原子操作不同,前者是操作系统级,后者是处理器级
- 原子变量的多重赋值是原子操作吗?
- 对标准类型使用原子操作
- 共享指针,C 版本的原子操作
- 即使在单线程程序中,共享指针是否在引用计数中使用原子操作
- 原子操作传播/可见性(原子负载与原子RMW负载)
- 为什么原子操作需要独家的缓存访问
- 在英特尔上自然对齐的POD类型的保证原子操作
- C++ 如何编写原子操作
- 原子操作示例'Concurrency in Action'的正确性
- 嵌套原子操作是否保证为原子操作
- 如何实现原子操作
- 如何使用原子操作fetch_or或test_and_set在指针中设置一点,而在C 11中不使用Amberare_
- 指针地址交换总是C++中的原子操作吗
- 何时不使用原子操作