我正在尝试使用boost :: atomic在Linux上执行multithreading同步。
但是,结果并不一致。
任何帮助将不胜感激。
谢谢
#include <boost/bind.hpp> #include <boost/threadpool.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread.hpp> #include <boost/atomic.hpp> boost::atomic<int> g(0) ; void f() { g.fetch_add(1, boost::memory_order_relaxed); return ; } const int threadnum = 10; int main() { boost::threadpool::fifo_pool tp(threadnum); for (int i = 0 ; i < threadnum ; ++i) tp.schedule(boost::bind(f)); tp.wait(); std::cout << g << std::endl ; return 0 ; }
我并不熟悉boost线程库或者boost :: threadpool,但是在我看来,当你访问g的值时线程并不一定完成,所以你会得到一些介于零和10之间的值。
这里是你的程序,修改为使用标准库,插入连接,以便在g的输出之前执行提取添加。
std::atomic<int> g(0); void f() { g.fetch_add(1, std::memory_order_relaxed); } int main() { const int threadnum = 10; std::vector<std::thread> v; for (int i = 0 ; i < threadnum ; ++i) v.push_back(std::thread(f)); for (auto &th : v) th.join(); std::cout << g << '\n'; }
如果你的程序仍然不一致,即使添加了tp.wait()
,那也是令人费解的。 添加应该在线程结束之前发生,并且我认为线程结束会与tp.wait()
同步,这在读取之前发生。 因此,即使您使用memory_order_relaxed,所有添加都应在g打印之前发生,因此打印值应为10。
以下是一些可能有所帮助的例子:
基本上,你试图用“锁定”来“保护”一个“关键区域”。
您可以设置或取消设置信号量。
或者你可以“交换”一个提升的“原子”变量。 例如(从上面的链接):
class spinlock { private: typedef enum {Locked, Unlocked} LockState; boost::atomic<LockState> state_; public: spinlock() : state_(Unlocked) {} lock() { while (state_.exchange(Locked, boost::memory_order_acquire) == Locked) { /* busy-wait */ } } unlock() { state_.store(Unlocked, boost::memory_order_release); } };