我有一套C ++函数:
funcB(){};
funcC(){};
funcA()
{
funcB();
funcC();
}
现在我想让funcA
原子,funcB
和funcC
内的funcA
调用应该以原子方式执行。有没有办法实现这个目标?
答案 0 :(得分:11)
您可以实现此目的的一种方法是使用新的(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
。答案 1 :(得分:6)
一般来说,不。非常精确地定义了原子操作。你想要的是信号量或互斥量。
答案 2 :(得分:1)
如果您使用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 ++中的其他同步构造一样,事务依赖于无数据争用的程序(例如,与同一内存位置的事务读取并发的非事务性写入是数据争用)。