- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我最近阅读了一些在同一个 union 中具有原子和字符的代码。像这样的东西
union U {
std::atomic<char> atomic;
char character;
};
// thread using the atomic
while (!atomic.compare_exchange_weak(old_value, old_value | mask, ...) { ... }
// thread using the character
character |= 0b1; // set the 1st bit or something
最佳答案
the code comments said that since a character can alias anything, we can safely operate on the atomic variable if we promise not to change the last few bits of the byte.
char
-can-alias-anything 并不能阻止它成为非原子变量的数据竞争,所以理论上是不允许的,更糟糕的是,
当由任何普通编译器(如 gcc、clang 或 MSVC)为任何普通 CPU(如 x86)编译时,它实际上已损坏。
char[]
中的相邻元素数组或结构是单独的位置(因此
it's not a race if two threads write c[0]
and c[1]
without synchronization )。但是结构体中相邻的位域不是单独的内存位置,并且使用
|=
在非原子
char
别名为与
atomic<char>
相同的地址绝对是相同的内存位置,无论在
|=
的右侧设置了哪些位.
atomic<int>
的中间字节更改为
atomic<char>
也不能保证是安全的。在类似于“普通”现代 CPU 的硬件上的大多数实现中,如果
atomic
都是无锁的,则类型对不同的
atomic<int/char>
类型的类型可能仍然是原子的,但内存排序语义实际上可能会被破坏,特别是如果它不是完全重叠的。
char*
, 不与
char
union . union 类型双关在 ISO C99 中是允许的,在 GNU C89 和 GNU C++ 中作为 GNU 扩展,也在一些其他 C++ 实现中。
character |= 1
将(在普通计算机上)编译为加载整个
char
的 asm , 修改临时值,然后将值存储回来。在 x86 上,这一切都可能发生在一个内存目的地
or
指令,如果编译器选择这样做(如果它稍后也需要该值,则不会这样做)。但即便如此,它仍然是一个非原子的 RMW,可以对其他位进行修改。
std::atomic
to get the other semantics you want...)
thread A | thread B
-------------------|--------------
read tmp=c=0000 |
|
| c|=0b1100 # atomically, leaving c = 1100
tmp |= 1 # tmp=1 |
store c = tmp
c
= 1,不是
1101
你希望。即高位的非原子加载/存储踩到了线程 B 的修改。
void t1(U &v, unsigned mask) {
// thread using the atomic
char old_value = v.atomic.load(std::memory_order_relaxed);
// with memory_order_seq_cst as the default for CAS
while (!v.atomic.compare_exchange_weak(old_value, old_value | mask)) {}
// v.atomic |= mask; // would have been easier and more efficient than CAS
}
t1(U&, unsigned int):
movzx eax, BYTE PTR [rdi] # atomic load of the old value
.L2:
mov edx, eax
or edx, esi # esi = mask (register arg)
lock cmpxchg BYTE PTR [rdi], dl # atomic CAS, uses AL implicitly as the expected value, same semantics as C++11 comp_exg seq_cst
jne .L2
ret
void t2(U &v) {
// thread using the character
v.character |= 0b1; // set the 1st bit or something
}
t2(U&):
or BYTE PTR [rdi], 1 # NON-ATOMIC RMW of the whole byte.
ret
v.character |= 1
的程序会很简单。在一个线程中,和一个原子
v.atomic ^= 0b1100000
(或等效于 CAS 循环)在另一个线程中。
or
在另一个线程中可能已经执行了奇数次 XOR 操作。或者为了使问题更容易看到,使用加法和
0x10
或者别的什么,所以不是 50% 的机会偶然是正确的,你只有 16 分之一的机会是高 4 位是正确的。
Will the cache have to be flushed for the thread that is trying to load the atomic integer?
关于c++ - std::atomic 与另一个字符 union ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48678396/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及预
为什么在 C# 中添加两个 char 结果是 int 类型? 例如,当我这样做时: var pr = 'R' + 'G' + 'B' + 'Y' + 'P'; pr 变量变为 int 类型。我希望它是
下面的代码可以编译,但 char 类型的行为与 int 类型的行为不同。 特别是 cout ::ikIsX >() ::ikIsX >() ::ikIsX >() using names
我正在寻找一个正则表达式,它可以匹配长度为 1 个或多个字符但不匹配 500 的内容。这将在 Rails 路由文件中使用,特别是用于处理异常。 路线.rb match '/500', to: 'err
对于 C 编程作业,我正在尝试编写几个头文件来检查所谓的“X 编程语言”的语法。我最近才开始,正在编写第一个头文件。这是我编写的代码: #ifndef _DeclarationsChecker_h_
为什么扩展的 ascii 字符(â、é 等)被替换为 字符? 我附上了一张图片...但我正在使用 PHP 从 MySQL 中提取数据,其中一些位置有扩展字符...我使用的是 Arial 字体。 您可以
我有一个与 R 中的断线相关的简单问题。 我正在尝试粘贴,但在获取(字符/数字)之间的断线时遇到问题。请注意,这些值包含在向量中(V1=81,V2=55,V3=25)我已经尝试过这段代码: cat(p
如何将 ANSI 字符 (char) 转换为 Unicode 字符 (wchar_t),反之亦然? 是否有用于此目的的任何跨平台源代码? 最佳答案 是的,在 中你有mbstowcs()和 wcsto
函数 fromCharCode 不适用于国际 ANSI 字符。例如,对于 ID 为 192 到 223 的俄语 ANSI (cp-1251) 字符,它返回特殊字符。如何解决这个问题? 我认为,需要将A
如果不喜欢,我想隐藏 id,但不起作用 SELECT * FROM character, character_actor WHERE character.id NOT LIKE character_a
现在这个程序成功地反转了键盘输入的单词。但是我想在我反转它之前“保存”指针中的单词,所以我可以比较两者,反转的和“原始的”,并检查它们是否是回文。我还没有太多经验,可能会出现比我知道的更多的错误,但我
Memcpy 和 memcmp 函数可以接受指针变量吗? char *p; char* q; memcpy(p,q,10); //will this work? memcmp(p,q,10); //w
恐怕我对一个相当过饱和的主题的细节有疑问,我搜索了很多,但找不到一个明确的答案来解决这个特定的明显-imho-重要的问题: 使用UTF-8将byte[]转换为String时,每个字节(8bit)都变成
我有一个奇怪的问题。我需要从 stat 命令打印输出字符串。 我已经编写了获取一些信息的代码。 import glob import os for file in glob.glob('system1
我正在使用 Java 并具有其值如下所示的字符串, String data = "vale-cx"; data = data.replaceAll("\\-", "\\-\\"); 我正在替换其中的“
String urlParameters = "login=test&password=te&ff"; 我有一个String urlParams,& - 是密码的一部分,如何使其转义,从而不被识别为分
大家好,我只想从此字符串中提取第一个字母: String str = "使 徒 行 傳 16:31 ERV-ZH"; 我只想获取这些字符: 使 徒 行 傳 并且不包括 ERV-ZH 仅数
这个问题已经有答案了: Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized point
所以, 我有一个字符**;它本质上是一个句子,带有指向该句子中每个单词的指针;即 'h''i''\0''w''o''r''l''d''\0''y''a''y''!''\0' 在这种情况下,我希望使用可
这个问题在这里已经有了答案: Using quotation marks inside quotation marks (12 个答案) 关闭 7 年前。 如何打印 " 字符? 我知道打印 % 符号
我是一名优秀的程序员,十分优秀!