假设我有两个进程,它们都使用shm_open和共享一个内存块,mmap并且存在一个共享同步原语 - 假设是一个信号量 - 确保对内存的独占访问。即没有竞争条件。
我的理解是,从返回的指针mmap仍必须标记为 volatile 以防止缓存读取。
现在,如何将例如 a 写入std::uint64_t内存中的任何对齐位置?
当然,我会简单地使用std::memcpy但它不适用于指向易失性内存的指针。
// Pointer to the shared memory, assume it is aligned correctly.
volatile unsigned char* ptr;
// Value to store, initialize "randomly" to prevent compiler
// optimization, for testing purposes.
std::uint64_t value = *reinterpret_cast<volatile std::uint64_t*>(nullptr);
// Store byte-by-byte
unsigned char* src = reinterpret_cast<unsigned char*>(&value);
for(std::size_t i=0;i<sizeof(value);++i)
ptr[i]=src[i];
Run Code Online (Sandbox Code Playgroud)
神箭。
我坚信这个解决方案是正确的,但即使使用-O3,也有 8 个 1 字节传输。这真的不是最优的。
因为我知道在我锁定内存时没有人会更改内存,所以也许 …
考虑这个功能:
void foo(int * p)
{
// something
}
Run Code Online (Sandbox Code Playgroud)
编译器是否可以假设没有其他线程会修改p指向的值?或者它是否必须表现得好像可以随时修改此值?
void bar(volatile int * p)
{
}
Run Code Online (Sandbox Code Playgroud)
如果没有,volatile关键字是否有帮助?GOTW#69指出,volatile编译器通常会忽略关键字.
编辑:显然对"编译器假定"这一短语存在一些误解.让我澄清一下:
*p在第一次读取时将值放入寄存器,然后使用它直到p超出范围.此时,它应该写入该*p内存地址的值.*p读取时,编译器都应该从内存中获取它的值,因为有一些其他线程可能会修改它.每次*p更改时,编译器都应将其写入内存,以便其他线程可以读取它优化编译器可以重新安排内存访问,CPU可以不按顺序执行指令.
问题是:用逗号运算符分隔语句是否保证了执行的确切顺序?或者唯一的方法是使用内存屏障(这是非常棘手和非标准的)?
如果不是,那么对于逗号分隔语句的执行顺序究竟是什么呢?
我有一个
volatile std::queue<int> requestQueue;
Run Code Online (Sandbox Code Playgroud)
当我尝试在函数内调用其任何方法(pop,push,empty,front等)时,例如:
while (!requestQueue.empty()){
...do something
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误.
robot.cpp:43:31: error: passing 'volatile std::queue<int>' as 'this'
argument of 'bool std::queue<_Tp, _Sequence>::empty()
const [with _Tp = int, _Sequence = std::deque<int, std::allocator<int> >]'
discards qualifiers [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
我在网上发现可能需要进行类型转换,但我不确定是否是这种情况.
有任何想法吗?提前致谢.
更新
1)程序使用这种数据结构来存储一系列请求,以便服务器可以以自己的服务速率获取请求.
2)volatile用于支持在不同核上运行的功能之间的数据共享.
3)我使用的库的文档说明了以下关于使用的文档
那么char上的操作是原子的吗?所以在线程AI中读取char T并在线程BI中写入相同的char T,这些标准操作是原子的吗?
char a;
#thread A
{
if(a & 0x01)
...
}
#thread B
{
a =0x01;
...
}
# ATOMIC?
Run Code Online (Sandbox Code Playgroud)
谢谢!
这是有关C ++标准的形式保证的问题。
该标准指出,std::memory_order_relaxed原子变量规则允许“凭空” /“出乎意料”的值出现。
但是对于非原子变量,这个例子可以有UB吗?是否r1 == r2 == 42有可能在C ++抽象机?== 42最初都不是变量,因此您不希望任何if主体执行,这意味着不会写入共享变量。
// Global state
int x = 0, y = 0;
// Thread 1:
r1 = x;
if (r1 == 42) y = r1;
// Thread 2:
r2 = y;
if (r2 == 42) x = 42;
Run Code Online (Sandbox Code Playgroud)
上面的示例改编自标准,该标准明确表示原子对象规范允许这种行为:
[注意:在以下示例中,要求确实允许r1 == r2 == 42,而x和y最初为零:
Run Code Online (Sandbox Code Playgroud)// Thread 1: r1 = x.load(memory_order_relaxed); if (r1 == 42) y.store(r1, memory_order_relaxed); // …
让我们假设如下:
我在 Linux / Mac OS 上有两个进程。
我有mmap共享内存(或在文件中)。
然后在这两个过程中我都有以下内容:
struct Data{
volatile int reload = 0; // using int because is more standard
// more things in the future...
};
void *mmap_memory = mmap(...);
Data *data = static_cast<Data *>(mmap_memory); // suppose size is sufficient and all OK
Run Code Online (Sandbox Code Playgroud)
然后在我做的其中一个过程中:
//...
data->reload = 1;
//...
Run Code Online (Sandbox Code Playgroud)
在另一个我做的:
while(...){
do_some_work();
//...
if (data->reload == 1)
do_reload();
}
Run Code Online (Sandbox Code Playgroud)
这会是线程/进程间安全的吗?
注意:
这对于 来说并不安全std::atomic<>,因为它不“承诺”有关共享内存的任何内容。此外,从两个不同的过程构建/销毁根本不清楚。
我目前正在编写ac/c ++ dll以供以后在Delphi中使用,我对Delphi中的线程比c/c ++更熟悉,尤其是boost.所以我想知道如何实现以下场景?
class CMyClass
{
private:
boost::thread* doStuffThread;
protected:
void doStuffExecute(void)
{
while(!isTerminationSignal()) // loop until termination signal
{
// do stuff
}
setTerminated(); // thread is finished
};
public:
CMyClass(void)
{
// create thread
this->doStuffThread = new boost::thread(boost::bind(&CMyClass::doStuffExecute, this));
};
~CMyClass(void)
{
// finish the thread
signalThreadTermination();
waitForThreadFinish();
delete this->doStuffThread;
// do other cleanup
};
}
Run Code Online (Sandbox Code Playgroud)
我有关于提升线程,信号和互斥量的红色无数文章,但我不明白,可能是因为它是星期五;)或者我认为这样做是不可行的?
关心丹尼尔
我们知道它可以用Java和JavaScript.
但问题是,可以在下面的条件永远评估为true 在C或C++?
if(a==1 && a==2 && a==3)
printf("SUCCESS");
Run Code Online (Sandbox Code Playgroud)
编辑
如果a是整数.
假设我在 C 中有一个这样的数组:
static volatile bool my_array[128] = {0};
Run Code Online (Sandbox Code Playgroud)
最重要的是,我有 128 个线程,每个线程在完成时都会写入不同的索引。true
这会产生一些问题吗?在 x64 上写入单个字节不会影响周围的字节,对吗?
我只是问,因为我不确定CPU/内存控制器/等是否总是读取8(或4)字节,然后写入它们。这会产生一些奇怪的竞争条件。
多谢