是否可以在C中只获取一个int,然后在不读取整个int并将其写回内存的情况下翻转它?
上下文: 试图在pthread中避免过多的锁定/解锁。
答案 0 :(得分:6)
您无法从内存中读取单个位,实际上您无法强制CPU只读取单个字节。它总是读取一个完整的缓存行,对于不同的CPU可能有不同的大小。
但从语言的角度来看,您可以使用位字段http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html
答案 1 :(得分:1)
据我所知,最低的操作单位是字节。也许您可以将int拆分为字节并从字中读取所需的字节并仅更改该字节。
答案 2 :(得分:1)
没有。为什么会这样,即使你可以从内存中读取一位,你仍然需要锁定以确保它是安全的。
答案 3 :(得分:1)
要么使用可以原子方式寻址的最小类型(char
在任何理智的架构上都可以,但是某些RISC垃圾不能在单个字节上进行原子操作)并接受你将浪费一些空间,使用锁定,或使用正确的原子基元(在asm,gcc builtins或C1x _Atomic
类型中)对各个位进行原子运算。
答案 4 :(得分:1)
以下是你如何做到比爷爷互斥体快50倍(我们做过这类事情的测试)。使用gcc原子操作。如果您的发行版包含它们,您也可以使用linux原子操作。
typedef union _foo {
struct {
unsigned int a:1,
b:6,
q:2;
} Data;
unsigned int n32;
} TFoo;
TFoo _GlobalFoo;
SomeFuncThatChangesFoo_A(int fNewA)
{
TFoo Old, New;
while(1) {
// get a copy of the current state
Old.n32 = _GlobalFoo.n32;
New.n32 = Old.n32;
New.Data.a = fNewA;
// compare and swap is the atomic operation.
// if _GlobalFoo hasn't changed since we copied it to "Old", then change _GlobalFoo to "New".
// __sync_bool_compare_and_swap works on basic types (8 bit, 16 bit, 32 bit, 64 bit, 128 bit
// depending upon architecture), which is why there is a union overlaying the 32 bit n32 over
// the actual data that the program uses, Data.
if (__sync_bool_compare_and_swap(_GlobalFoo.n32, Old.n32, New.n32))
break; // successfully changed
// if we get here, the global was changed by another thread, so we just loop back, get the new value
// and try again.
} // concurrency loop
}
精明的线程可能会认为“Old.n32 = _GlobalFoo.n32;”这一行如果编译器选择非原子方式来执行复制,则可以在竞争中复制垃圾。但是,__sync_bool_compare_and_swap会因为当前状态的错误副本而失败,因此不会造成任何伤害。
欢呼声。
答案 5 :(得分:0)
这可能是可能的,但只能以非便携式,非标准方式进行,并且只有在您的平台支持时才可以。一些ARM CPU(例如Cortex-M3和M4)实现“位带”,为地址空间区域提供位级寻址。
但一般来说,读/写的最小单位(或等效的,最小的可寻址单位)是char
。