C++ 0x指定std::atomic用于线程安全原子访问变量的模板.此模板包含一个成员函数std :: atomic :: exchange,它以"this"原子方式存储一个新值,并检索"this"的现有值.
Win32有类似的功能: InterlockedExchange
现在,这些操作的作用很简单:原子读取 - 修改.
我不明白的是这个操作的重点是什么.返回的值是"无意义的",因为一旦我可以检查返回值,另一个线程可能已经覆盖了它.
那么这个用例是什么?在我将新值写入变量之前,有哪些值的信息可以告诉我什么?
注意:compare_exchange/ InterlockedCompareExchange语义对我有意义,但不是简单的交换语义.
根据文档,AtomicInteger.incrementAndGet()是原子的.但是,在下面的源代码中,如果另一个线程在"返回下一个"之前交错怎么办?那么"下一步"会不正确吗?
public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
Run Code Online (Sandbox Code Playgroud) Atomic指令是什么意思?
以下内容如何成为Atomic?
检查并设置
int TestAndSet(int *x){
register int temp = *x;
*x = 1;
return temp;
}
Run Code Online (Sandbox Code Playgroud)
从软件的角度来看,如果不想使用非阻塞同步原语,那么如何确保指令的原子性?是否只能在硬件或某些装配级指令优化中使用?
language-agnostic synchronization test-and-set nonblocking atomicity
我在我的多线程代码中使用incrementAndGet方法AtomicLong来衡量我们的一些客户端代码的性能.
@Override
public void run() {
long start = System.nanoTime();
attributes = client.getAttributes(columnsList);
long end = System.nanoTime() - start;
final AtomicLong before = select.putIfAbsent(end / 1000000L, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet();
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我试图测量多少时间 -
client.getAttributes(columnsList);
正在服用.
据我所知,incrementAndGet方法将以原子方式将当前值增加1.这意味着每个线程可能会等待其他线程递增值.我对吗?意味着它会被封锁?
这也会影响我测量任何方法性能的方式吗?这意味着它会为该测量增加一些额外的时间吗?
为什么我要问这是因为我试图对大部分客户端代码和服务器端代码进行基准测试,如果我需要测量每种方法花费多少时间,那么我这样做就像这样 -
无论我想测量什么代码,我通常将下面的行放在该方法之上
long start = System.nanoTime();
而这两条线路采用相同的方法但却有所不同 ConcurrentHashMap
long end = System.nanoTime() - start;
final AtomicLong before = select.putIfAbsent(end / 1000000L, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet(); …Run Code Online (Sandbox Code Playgroud) 我正在写Python 2.7剧本.
总之,这个脚本每晚都在运行Linux并激活多个进程.
我想确保这个脚本不是并行运行多次(基本上是试图模仿Singleton模式但是在应用程序级别).
代码示例
def main():
# before doing anything, I'd like to know whether this
# script was activated and alive.
# if so, error out
# do something
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
建议
天真的解决方案是创建某种锁文件,它充当互斥锁.
我们要做的第一件事就是检查这个文件是否存在.如果是这样,那么脚本的其他实例已经创建了它,我们应该出错.脚本完成后,我们删除此文件.
我假设这个解决方案可行,只要文件系统上的操作是原子的.
履行
import os, sys
lock_file_path = ".lock_script"
def lock_mutex():
if os.path.exists(lock_mutex_path):
print "Error: script was already activated."
sys.exit(-1)
else:
file = open(lock_mutex_path, 'w')
def unlock_mutex():
assert( os.path.exists(lock_mutex_path))
os.remove(lock_mutex_path)
def main():
try:
lock_mutex()
# do …Run Code Online (Sandbox Code Playgroud) 考虑一个架构:
var userSchema = mongoose.Schema({
...
followers: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
following: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }]
...
}
Run Code Online (Sandbox Code Playgroud)
当userA下面userB,userB是被推动userA.following而userA在被推动userB.followers.这两项操作都需要.save().
什么是好方法 - 也许是概念性的 - 确保如果其中一个.save()失败,两个文件都保持不变?
在多线程(Linux/amd64,Pthreads,C11)应用程序中,我有一个struct(momitem_st在monimelt.h中)包含两个字段
uint16_t i_paylkind;
void* i_payload;
Run Code Online (Sandbox Code Playgroud)
(如果需要,我可以将类型更改为i_paylkind 其他整数类型,例如uintptr_t 或atomic_uint)
FWIW i_paylkind 是一个判别式,用于定义指向的实际struct 运行时类型i_payload.
是否有可能以原子方式访问这两个字段(其他线程访问它们struct).当然我也有一个pthread_mutex_t i_mtx;可以锁定(使用pthread_mutex_lock)的相同结构.但出于性能原因,我可能想避免这种情况(可能是事务性内存可能相关)
它似乎<stdtomic.h>没有提供任何机械.
(与我的MELT显示器 GPLv3 +软件有关的问题)
这是我对原子性的理解,它用于确保一个值可以整体而不是部分地读/写.例如,64位值实际上是两个32位DWORD(假设此处为x86),在线程之间共享时必须是原子的,以便同时读/写两个DWORD.这样一个线程就无法读取未更新的半变量.你如何保证原子性?
此外,我的理解是,波动性根本不能保证线程安全.真的吗?
我已经看到它暗示许多只是原子/易失性的地方是线程安全的.我不知道那是怎么回事.我是否还需要一个内存屏障来确保在实际可以保证在另一个线程中读/写之前,读/写任何原子或其他值?
例如,假设我创建了一个挂起的线程,做一些计算将一些值更改为线程可用的结构然后恢复,例如:
HANDLE hThread = CreateThread(NULL, 0, thread_entry, (void *)&data, CREATE_SUSPENDED, NULL);
data->val64 = SomeCalculation();
ResumeThread(hThread);
Run Code Online (Sandbox Code Playgroud)
我想这将取决于ResumeThread中的任何内存障碍?我应该为val64进行互锁交换吗?如果线程正在运行,那会怎么改变呢?
我确定我在这里问了很多,但基本上我想弄清楚的是我在标题中提出的问题:对Windows中的原子性,波动性和线程安全性的一个很好的解释.谢谢
我正在阅读 Linux 信号量的实现。由于原子性,信号和等待(在源代码中向上和向下)使用自旋锁。然后我看到 Linux 在 spin_lock_irqsave 中禁用了中断并在 spin_unlock 中重新启用了中断。这让我很困惑。在我看来,在关键部分禁用中断真的没有意义。
例如,proc A(当前处于活动状态)获取了锁,proc B(阻塞)正在等待锁,proc C 正在做一些不相关的事情。在 A 和 B 之间的临界区内上下文切换到 C 是非常有意义的。即使 C 也尝试获取锁,由于锁已经被 A 锁定,结果将是 C 被阻塞而 A 恢复执行。
因此,我不知道为什么 Linux 决定禁用由自旋锁保护的临界区中的中断。它可能不会导致任何问题,但对我来说似乎是一个多余的操作。
与此线程相关,我有一个 FIFO,它应该可以跨 Cortex M4 上的不同中断工作。
头部索引必须是
移动 FIFO 头的函数看起来与此类似(在实际代码中也有检查头是否溢出,但这是主要思想):
#include <stdatomic.h>
#include <stdint.h>
#define FIFO_LEN 1024
extern _Atomic int32_t _head;
int32_t acquire_head(void)
{
while (1)
{
int32_t old_h = atomic_load(&_head);
int32_t new_h = (old_h + 1) & (FIFO_LEN - 1);
if (atomic_compare_exchange_strong(&_head, &old_h, new_h))
{
return old_h;
}
}
}
Run Code Online (Sandbox Code Playgroud)
GCC 会将其编译为:
acquire_head:
ldr r2, .L8
.L2:
// int32_t old_h = atomic_load(&_head);
dmb ish
ldr r1, [r2]
dmb ish
// int32_t new_h …Run Code Online (Sandbox Code Playgroud) atomicity ×10
c ×2
c11 ×2
java ×2
assembly ×1
atomic ×1
atomic-long ×1
c++11 ×1
gcc ×1
interrupt ×1
linux ×1
mongoose ×1
mutex ×1
node.js ×1
nonblocking ×1
pthreads ×1
python ×1
python-2.7 ×1
test-and-set ×1
volatility ×1
windows ×1