我有一个关于MySQL的问题,但一直无法找到答案.我知道在MySQL中默认启用自动提交.我需要在一个事务中从命令行运行一些更新查询,但我不知道MySQL将如何处理它们.如果我有这样的事情:
mysql -uroot -proot -e 'QUERY 1; QUERY 2; QUERY3'
Run Code Online (Sandbox Code Playgroud)
它会作为一个事务执行还是MySQL会自动提交每个语句?我需要确保原子性.
首先,我知道volatile不会使多个操作(如i++)原子化.这个问题是关于单个读或写操作.
我最初的理解是volatile只强制执行内存屏障(即其他线程将能够看到更新的值).
现在我注意到JLS第17.7节说明volatile还会产生单个读或写原子.例如,给定两个线程,两者都写入不同的值volatile long x,然后x最终将代表其中一个值.
我很好奇这是怎么回事.在32位系统上,如果两个线程并行写入64位并且没有"正确"同步(即某种锁定),则结果应该是混合.为清楚起见,让我们使用一个例子,其中线程1写入0L,而线程2将-1L写入相同的64位存储器位置.
T1 writes lower 32 bit
T2 writes lower 32 bit
T2 writes upper 32 bit
T1 writes upper 32 bit
Run Code Online (Sandbox Code Playgroud)
结果可能是0x0000FFFF,这是不希望的.如何volatile防止这种情况?
我还在别处读过,这通常不会降低性能.如何以极小的速度影响同步写入?
我正在阅读 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) 我花了几个小时试图回答我的问题,但找不到任何令人满意的答案。
由于 ARM Cortex-M 内核没有任何指令来读取全局中断掩码(PRIMASK 寄存器)的状态并立即禁用它,因此所有框架都使用以下两条指令的序列:
mrs r0, PRIMASK ; Read current state
cpsid i ; Mask IRQs
Run Code Online (Sandbox Code Playgroud)
但是没有解释,为什么这段代码被认为是原子的......当IRQ出现在这两条指令的执行之间并且IRQ处理程序改变PRIMASK的状态时会发生什么?喜欢
mrs r0, PRIMASK ; Read current state
; Some weird IRQ handling happens here and changes PRIMASK
cpsid i ; Mask IRQs
Run Code Online (Sandbox Code Playgroud)
由于这段代码被广泛使用,我怀疑(架构?)设计永远不会发生这种情况。有人可以向我解释为什么吗?:-) 谢谢!
假设您有以下课程
public class AccessStatistics {
private final int noPages, noErrors;
public AccessStatistics(int noPages, int noErrors) {
this.noPages = noPages;
this.noErrors = noErrors;
}
public int getNoPages() { return noPages; }
public int getNoErrors() { return noErrors; }
}
Run Code Online (Sandbox Code Playgroud)
然后执行以下代码
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors); …Run Code Online (Sandbox Code Playgroud) 问题是64位加载/存储操作何时被认为是原子操作.
我正在研究Java书籍中的并发包。我不太了解本书中有关CAS操作的内容。下面的代码示例是counter本书中的线程安全类。
public class Counter{
private AtomicInteger count = new AtomicInteger();
public void increment(){
count.getAndIncrement(); //atomic operation
}
....
}
Run Code Online (Sandbox Code Playgroud)
这是书中所说的。
实际上,即使诸如这样的方法也要
getAndIncrement()花费几个步骤来执行。此实现现在是线程安全的,因此称为CAS。CAS代表“比较并交换”。大多数现代CPU都有一组CAS指令。现在正在发生的事情的基本概述如下:
- 存储在count中的值将被复制到一个临时变量中。
- 临时变量增加。
- 将当前计数的值与原始值进行比较。如果未更改,则将旧值替换为新值。
好吧,我明白它关于多个步骤的说法。我不太了解的是枚举步骤中正在发生的事情。
- 存储在count中的值将被复制到一个临时变量中。
该临时变量在哪里?它在主存储器中,注册吗?还是特定于CPU体系结构?
- 将当前计数的值与原始值进行比较。如果未更改,则将旧值替换为新值。
原始值存储在哪里?不能是临时变量。那个人正在被修改,对吧?我想念什么?
谢谢
我想在向外部系统发送请求时实施严格的循环调度.有两个外部系统服务器.第一个请求应该转到'System1',第二个请求必须转到'System2',然后转到'System1',依此类推.
因为我只有两个服务器来发送请求,并且因为我想要最大性能而没有任何阻塞和上下文切换,所以我已经使用了AtomicBoolean,因为它使用了CAS操作.
我的实现类
1. RoundRobinTest.java
package com.concurrency;
import java.util.Iterator;
public class RoundRobinTest
{
public static void main(String[] args)
{
for (int i = 0; i < 500; i++)
{
new Thread(new RoundRobinLogic()).start();
}
try
{
// Giving a few seconds for the threads to complete
Thread.currentThread().sleep(2000);
Iterator<String> output = RoundRobinLogic.output.iterator();
int i=0;
while (output.hasNext())
{
System.out.println(i+++":"+output.next());
// Sleeping after each out.print
Thread.currentThread().sleep(20);
}
}
catch (Exception ex)
{
// do nothing
}
}
}
Run Code Online (Sandbox Code Playgroud)
2.RoundRobinLogic.java(具有静态AtomicBoolean对象的类)
package com.concurrency;
import java.util.Queue; …Run Code Online (Sandbox Code Playgroud) 我正在寻找以下原子版:
import os
def tryMakeFile(filename):
try:
with open(filename) as _:
return False
except FileNotFoundError:
with open(filename, mode='a') as _:
return True
Run Code Online (Sandbox Code Playgroud)
(请不要在这里评论文体问题 - 我知道这个代码在很多方面都很糟糕,但它足以说明我的问题.)
换句话说,我正在寻找一种方法来检查文件是否存在,如果不存在则创建它,在Python中,以我知道发生了哪种方式.但是这样做的方式是在多个进程之间没有竞争条件(在我给出的示例代码中,两个进程都可以认为他们创建了文件,如果第二个进程运行,而第一个进程在第一个和第二个进程之间暂停调用).
或者,换句话说,我正在寻找与Java的Files.createFile调用相当的Python .
编辑:请注意,当我说"Python"时,我的意思是"便携式Python".说"使用这个库*(*这个库只在Windows上可用,或者不在Windows上,或者仅在蓝月亮后的第二个星期二)"并不是我想要的.我正在寻找明确原子的东西,标准库和/或内置的一部分,并且它可以在通用平台上使用.