使用C 中的原始操作员的异步线的相互排除
Mutual exclusion for an asynchronous thread using primitive operators in c++
我一直在尝试使用c 原语操作员和变量,例如 int , if 和,而em>要开发螺纹安全机制。
我的想法是使用两个整数变量,称为 sync 和 lock ,增加和检查 sync sync and在此之后,逐步检查锁定。如果所有检查都成功了,则可以保证锁,但是如果检查不成功,它会再次尝试。
看来我的想法在最终验证中断言。
#include <assert.h>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
class Resource {
// Shared resource to be thread safe.
int resource;
// Mutual exclusion variables.
volatile int lock;
volatile int sync;
public:
Resource() : resource( 0 ), lock( 0 ), sync( 0 ) {}
~Resource() {}
int sharedResource() {
return resource;
}
void sharedResourceAction( std::string id ) {
bool done;
do {
int oldSync = sync;
// ++ should be atomic.
sync++;
if ( sync == oldSync + 1 ) {
// ++ should be atomic.
lock++;
if ( lock == 1 ) {
// For the sake of the example, the read-modify-write
// is not atomic and not thread safe if threre is no
// mutex surronding it.
int oldResource = resource;
resource = oldResource + 1;
done = true;
}
// -- should be atomic.
lock--;
}
if ( !done ) {
// Pseudo randomic sleep to unlock the race condition
// between the threads.
std::this_thread::sleep_for(
std::chrono::microseconds( resource % 5 ) );
}
} while( !done );
}
};
static const int maxThreads = 10;
static const int maxThreadActions = 1000;
void threadAction( Resource& resource, std::string& name ) {
for ( int i = 0; i < maxThreadActions; i++) {
resource.sharedResourceAction( name );
}
}
int main() {
std::vector< std::thread* > threadVec;
Resource resource;
// Create the threads.
for (int i = 0; i < maxThreads; ++i) {
std::string name = "t";
name += std::to_string( i );
std::thread *thread = new std::thread( threadAction,
std::ref( resource ),
std::ref( name ) );
threadVec.push_back( thread );
}
// Join the threads.
for ( auto threadVecIter = threadVec.begin();
threadVecIter != threadVec.end(); threadVecIter++ ) {
(*threadVecIter)->join();
}
std::cout << "Shared resource is " << resource.sharedResource()
<< std::endl;
assert( resource.sharedResource() == ( maxThreads * maxThreadActions ) );
return 0;
}
是否存在仅使用原始变量和操作员保护共享资源的线程安全机制?
no,有几个原因为什么不起作用
首先,标准描述了它不起作用。您(明确(有一个读/写和写入/写入比赛条件,并且标准禁止此。
其次,++i
绝不是原子。即使在主流英特尔处理器上,也不是 - 当需要是lock inc
指令时,通常是inc
指令。
第三,挥发性在C 中没有螺纹含义,就像Java或C#中一样。它既不是必要的也不是足够的来实现与螺纹安全有关的任何事情(在挥发性的volatile:/ms之类的令人讨厌的编译器扩展程序之外(。有关C 挥发性的更多信息,请参见此答案。
您的代码中可能还有更多问题,但此列表应该足以劝阻您。
编辑:为了实际回答您的最后一个问题 - 不,我认为以标准的方式实现原始类型和操作的线程安全机制是不可能的。基本上,您需要获得内存 - 辅助,CPU和编译器都同意在实施线程安全机制时不要执行某些转换。通常,这意味着您需要使用编译器挂钩或在标准之外保证,并且还需要了解最终目标CPU的保证或内在的实现。
volatile
绝对不适合多线程:
在执行线程中,通过 挥发性的glvalues不能重新排序,而不是可观察到的副作用 (包括其他挥发性访问(,以之前进行测序或 在同一线程中进行了测序,但此顺序不是 由于挥发性访问,保证可以通过另一个线程观察到 不建立线程间同步。
此外,挥发性 访问不是原子质(并发读写是数据竞赛(和 请勿订购内存(非易失性内存访问可能是自由的 在挥发性访问中重新排序(。
如果您想在整数上进行原子操作,则适当的方法是使用std::atomic<int>
。这使您可以保证其他线程会观察到的内存排序。如果您真的想执行这种无锁的编程,则应坐下并吸收内存模型文档,如果您像我一样,请重新考虑尝试在试图阻止头部爆炸时尝试无锁的编程。
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- Geeksforgeeks C 程序故障排除:IEE 754 表示法为十进制
- 如何在C++中实现带有packaged_task的异步等待循环?
- 创建 Spdlog 异步文件记录器时遇到困难
- C ++异步键盘输入(标准方式)
- 如何从整个磁盘中排除要装载的一个文件
- 如何进行故障排除:未定义对"非虚拟 thunk to ..."的引用
- 在 gtkmm 中异步加载图像
- 如何在 C++ 的输出中排除 SENTINEL 值?
- 带有 Boost.Beast 的异步读取标头
- 如何在 c++ 中异步调用静态方法?
- libcurl :C++处理多个异步请求
- 如何在C++上启动异步线程
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 增强 ASIO 和串行端口异步读取
- 使用 Qt5 SQL 进行异步数据库访问的策略
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- C++中真正的异步文件 IO
- 提升::Asio 异步聊天客户端停止与服务器通信
- 使用C 中的原始操作员的异步线的相互排除