我正在尝试编译一个包含原子 headerr 的 C++ 文件,
我收到此错误:
#error <atomic> is not supported on this single threaded system
Run Code Online (Sandbox Code Playgroud)
我使用交叉编译的 clang。我在 redHat 6.9 上运行
我正在学习同步,现在我对原子操作的定义感到困惑。经过查找,只能得知原子操作是不可中断的操作。
那么,原子操作不是只对单处理器系统有效吗,因为对于多处理器系统,许多操作可以同时运行?
我不确定以下语句有什么问题,它给了我编译错误。我们不能将“auto”与原子变量一起使用吗?
#include <iostream>
#include<future>
#include <atomic>
using namespace std;
int main()
{
atomic<int> value(10);
auto NewValue = value;
}
Run Code Online (Sandbox Code Playgroud)
但如果我用“int”替换“auto”,它就可以工作。为什么?
int main()
{
atomic<int> value(10);
int NewValue = value;
}
Run Code Online (Sandbox Code Playgroud)
“auto”编译错误
||=== Build: Debug in Hello (compiler: GNU GCC Compiler) ===|
F:\3d\C++CodeProject\Hello\main.cpp||In function 'int main()':|
F:\3d\C++CodeProject\Hello\main.cpp|11|error: use of deleted function
'std::atomic<int>::atomic(const std::atomic<int>&)'|
C:\Program Files
(x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\atomic|612|note:
declared here|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
Run Code Online (Sandbox Code Playgroud) 我知道atomic<T>当多个线程正在读取和写入变量时,将会对类型“T”变量应用锁定,确保只有其中一个线程正在执行读/写操作。
但在多CPU核心计算机中,线程可以运行在不同的核心上,不同的核心会有不同的L1-cache、L2-cache,同时共享L3-cache。我们知道有时C++编译器会优化将变量存储在寄存器中,这样如果变量没有存储在内存中,那么该变量上的不同core-cache之间就没有内存同步。
如果atomic<T>编译器将变量优化为某个寄存器变量,那么它不会存储在内存中,当一个核心写入其值时,另一个核心可能会读出陈旧的值,对吗?这个数据一致性有保证吗?
我正在编写一个 CUDA 程序,它在共享内存中定义了一个数组。我需要做的是只允许一个线程写入此数组中的每个索引,即到达此写入指令的第一个线程应更改其值,但同一扭曲或下一个扭曲中的任何其他线程应读取写入的值。
这是代码片段:
char* seq_copied = seqs + (njobNew * halfLength); //this is the shared memory array
if (seq_copied[seq_1_index] == false) { //here is the condition that I need to check with only one thread
seq_copied[seq_1_index] = true; //and this is the write that should be written by only one thread
printf("copy seq_shared seq_1_index = %d, block = %d \n", seq_1_index, blockIdx.x);
}
Run Code Online (Sandbox Code Playgroud)
现在发生的情况是,warp 中的所有线程都执行这些确切的指令序列,因此 if 条件中的剩余代码被执行了 32 次。我只需要执行一次。
我怎样才能做到这一点?
我正在阅读一些源代码并locking在 Clojure 中遇到了用法。这让我想到了 atom 版本。那么2个代码片段之间有什么区别,我认为它们做同样的事情?
(def lock (Object.))
(locking lock
...some operation)
Run Code Online (Sandbox Code Playgroud)
(def state (atom true))
(when @state
(reset! state false)
...some operation
(reset! state true))
Run Code Online (Sandbox Code Playgroud) 我有一些代码synchronized用来保护我递增的计数器count++。
我希望我正确地保护了代码部分,因此得到2_0000_0000了结果,因为count在多次执行它之后,这将是正确的值,多线程。
但是,在运行代码时,我得到一个低于预期的值2_0000_0000,就好像我synchronized没有正确保护代码部分一样。
为什么会这样,我做错了什么?
public class Test {
private static Integer count = 0;
private static void add10K() {
long idx = 0;
while (idx++ < 1_0000_0000) {
synchronized (count){
count += 1;
}
}
}
public static long calc() {
Thread th1 = new Thread(Test::add10K);
Thread th2 = new Thread(Test::add10K);
th1.start();
th2.start();
try {
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return count;
}
public …Run Code Online (Sandbox Code Playgroud) 我在实践中研究JAVA并发,发现原子操作的定义如下:
如果从执行 A 的线程的角度来看,操作 A、B 彼此是原子的,当另一个线程执行 B 时,B 要么全部执行完毕,要么全部执行完毕。原子操作是指对同一数据进行操作的所有操作(包括其本身)都是原子的。
假设我有两个线程 A 和 B 都访问 AtomicLong 变量计数。
假设线程 A 读取 count 而线程 B 正忙于执行 count.incrementAndGe() 操作。
在这种情况下,根据上面的定义(要么所有 B 都已执行,要么没有执行):
A) ThreadA 查看之前的 count 值(因为 count 尚未更新)
或者
B) ThreadA 将等待,直到 ThreadB 完成操作并查看最新值。
根据我的理解,它应该是 B,因为否则我们仍然可能出现竞争条件。
鉴于以下情况:
class Foo
{
public:
void Increment()
{
_InterlockedIncrement(&m_value); // OSIncrementAtomic
}
long GetValue()
{
return m_value;
}
private:
long m_value;
};
Run Code Online (Sandbox Code Playgroud)
读取时是否需要内存屏障m_value?我的理解是,这_InterlockedIncrement将生成完整的内存屏障,并确保在发生任何后续加载之前存储该值。因此,从这方面来看,这听起来很安全,但是,m_value完全可以缓存,即可以GetValue()返回陈旧的值,即使在原子递增时也是如此?
Jeff Preshing 的优秀文章供参考:https://preshing.com/20120515/memory-reordering-caught-in-the-act/
其他上下文:
我正在关注一系列有关无锁编程的文章,特别是查看变量的用法unfinishedJobs以及此处的潜在实现HasJobCompleted:
https: //blog.molecular-matters.com/2015/08 /24/job-system-2-0-lock-free-work-stealing-part-1-basics/
void Wait(const Job* job)
{
// wait until the job has completed. in the meantime, work on any other job.
while (!HasJobCompleted(job))
{
Job* nextJob = GetJob();
if (nextJob)
{
Execute(nextJob);
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以通过将 unfinishedJobs …
从这个问题扩展(How to do anatomicincrement and fetch in C?)
在 C 中,使用 Clang 编译器,我怎样才能做原子等价的事情
const int v = ++x
据我了解,v = atomic_fetch_add(&x, 1)将返回原始值(即v = x++),这是一个后增量。
如何返回 x 的更新值?
注意:这个问题是关于 C 的,任何带有“use std::atomic<>”的回复都将相应地被否决。