我在scala中有一个编译器错误,我不知道它引用了什么:
假设这些声明:
trait Abstract {
type MyType
}
trait AInner
trait A extends Abstract{
type MyType <: AInner
}
trait BInner {
def bMethod : Int
}
trait B extends Abstract with A{
override type MyType <: BInner with A#MyType
}
Run Code Online (Sandbox Code Playgroud)
我在这里尝试实现的(在trait中B
)是进一步限制MyType
声明的类型Abstract
,因此任何类型的值都MyType
必须扩展MyType
mixin树中的所有s.
编译器给我这个消息(如标题所示):
类型MyType是一个易失性类型; 不能覆盖具有非易失性上限的类型.我理解,类型易变性在这里发生是因为类型连接with A#MyType
,错误的一部分:具有非易失性上限的类型可能是指类型声明type MyType <: AInner
,其中AInner
不是抽象类型,因此是非易失性的.
受这个问题的启发,我写了测试:
public class Main {
private static final long TEST_NUMBERS = 5L;
private static final long ITERATION_NUMBER = 100000L;
private static long value;
public static void main(final String [] args) throws Throwable {
for(int i=0; i<TEST_NUMBERS; i++) {
value = 0;
final Thread incrementor = new Thread(new Incrementor());
final Thread checker = new Thread(new Checker());
incrementer.start();
checker.start();
checker.join();
incrementer.join();
}
}
static class Incrementor implements Runnable {
public void run() {
for(int i=0; i<ITERATION_NUMBER; i++){
++value;
}
} …
Run Code Online (Sandbox Code Playgroud) 在嵌入式环境中(使用MSP430),我看到了部分写入非易失性存储器导致的一些数据损坏.这似乎是由写入期间的功率损耗(对FRAM或信息段)造成的.
我正在使用CRC验证存储在这些位置的数据.
我的问题是,防止这种"部分写入"腐败的正确方法是什么?目前,我已修改我的代码以写入两个单独的FRAM位置.因此,如果一个写入被中断导致CRC无效,则另一个位置应保持有效.这是一种常见做法吗?我是否需要为任何非易失性存储器实现这种双写行为?
我最近在SO和其他地方读过很多关于线程内存管理的内容,特别是volatile
关键字的使用.然而,我开始对这个概念有相当的自信,为了充分理解它所具有的效果,我想尝试并运行一些实验来说明它.
这是我的设置:我有一个生产者线程(它从麦克风读取音频数据,与我之前的问题相关,但实际数据无关紧要),它将数据传递byte[]
给单独的消费者线程.线程之间共享数据的方式是我实验中的主要变量:我尝试了一个ArrayBlockingQueue
; 我尝试过共享volatile byte[]
引用(本博客文章中array = array
推荐的自引用); 我也尝试了一个没有自我参考的普通非易失性.两个线程也会在数据写入时将数据写入磁盘.byte[]
我希望发现,在运行一段时间之后,非易失性byte[]
版本在生产者试图共享的数据与消费者读取数据之间的差异会因为某些内存写入时间不可见而导致数据不一致由于为确保发布内存写入所采取的预防措施,其他两个版本将由每个线程记录完全相同的数据.然而,无论我使用何种方法,我都会发现100%的准确率.
我已经可以想到为什么会发生这种情况的几种可能性,但我的主要问题是: 在什么条件下写入非易失性变量看不见另一个线程,据我所知,这是完整的观点volatile
?我可以强制这些条件用于实验目的吗?
到目前为止我的想法是:
任何人都可以建议我如何设计这样的实验或解释为什么我的想法有缺陷?
非常感谢.
在英特尔ISA扩展手册中,描述pcommit
有点神秘:
该
PCOMMIT
指令导致某些商店到内存的操作,以永久内存范围,以成为持续性(断电保护).具体而言,PCOMMIT
适用于已被内存接受的那些商店.
[...]
如果PCOMMIT
在存储器接受到持久存储器范围的存储之后执行,则当存储PCOMMIT
变为全局可见时,存储将变为持久存储.
[...]
只有在已经写入目标非易失性设备或某些中间电源故障保护存储/缓冲区之后,存储到持久性存储器的数据才会变得持久(持久).
它将持久存储器范围,存储器接受的存储,存储成为持久存储器和非易失性设备1等概念命名.
确切的背景是什么?
1这不是传统的NV设备,如NOR Flash ROM或NVMe设备(读取:新的SSD),因为它们位于可控数量的桥之后,包括减法解码,这是CPU无法控制的.
下面的代码示例来自一个介绍其效果的中文博客volatile
.左边是C代码; 另一个是生成的汇编代码.
// cordering.c gcc -O2 -S -masm=intel cordering.c
int A;
volatile int B;
void foo() mov eax, DWORD PTR B[rip]
{ mov DWORD PTR B[rip], 0
A = B + 1; add eax, 1
B = 0; mov DWORD PTR A[rip], eax
} ret
Run Code Online (Sandbox Code Playgroud)
正如我们在汇编代码中看到的那样,副作用A
放在副作用之后B
,即使B
是volatile
合格的.但是,cppreference.com说:
[W]在单个执行线程中,易失性访问不能优化或重新排序,具有在易失性访问之前排序或排序的另一个可见副作用.
这里的副作用A
之前是排序的B
,所以我认为编译器执行此操作是非法的.我对吗?
作为补充,博客说如果我们想要保证a volatile
和non-volatile
type 之间的顺序,我们需要同时做到volatile
:
// cordering.c gcc …
Run Code Online (Sandbox Code Playgroud) 我正在创建一个自定义操作系统,有没有什么方法可以在程序集中存储数据(几乎像文件系统),以便在计算机关闭并重新打开时数据仍然存在?
volatile int vfoo = 0;
void func()
{
int bar;
do
{
bar = vfoo; // L.7
}while(bar!=1);
return;
}
Run Code Online (Sandbox Code Playgroud)
此代码忙等待变量变为1
。如果第一遍vfoo
未设置为1
,我会卡在里面吗。
这段代码编译时没有警告。标准对此有何看法?
vfoo
被声明为volatile
. 因此,读这个变量应该不进行优化。volatile
资格。是否允许编译器优化写入bar
?.ie 编译器将对 进行读取访问vfoo
,并允许丢弃此值而不将其分配给bar
(在 L.7)。我正在使用Python Queue cclass来管理多个工作线程之间共享的任务列表.实际的代码是很棒的,我仍然在使它完全没有bug.工作线程会不时崩溃,我必须重新启动整个例程.在此过程中,我将丢失已排队的所有任务.有没有办法将队列保存到文件中,这样每当我重新启动进程时,任务列表都会从该文件中预先加载?
首先想到的是,当我将任务放入队列时,我应该同时读取和写入文件.但是,这并没有给我queue.task_done()的功能,可能不是最优化的解决方案.任何想法将不胜感激.
关于volatile变量如何从"主"内存有效访问,我有点困惑.它与具有本地副本的变量(非易失性)有什么不同?什么是每当多个线程访问非易失性的典型工作流程VS volatile变量?我的意思是他们如何在幕后工作?
volatile写入是否确保在一个线程中的任何写入(非易失性/易失性写入)在其他线程可见之前发生?
下面给出的代码总是会产生90,80
输出吗?
public class MyClass
{
private boolean flag = false;
private volatile int volatileInt = 0;
private int nonVolatileInt = 0;
public void initVariables()
{
nonVolatileInt = 90; // non-volatile write
volatileInt = 80; // volatile write
flag = true; // non-volatile write
}
public void readVariables()
{
while (flag == false)
{}
System.out.println(nonVolatileInt + ","+ volatileInt);
}
public static void main(String st[])
{
final MyClass myClass = new MyClass();
Thread writer = new Thread( new Runnable() …
Run Code Online (Sandbox Code Playgroud) non-volatile ×11
volatile ×5
java ×4
memory ×2
assembly ×1
c ×1
c++ ×1
concurrency ×1
embedded ×1
file ×1
jit ×1
msp430 ×1
persistence ×1
python ×1
queue ×1
scala ×1
type-bounds ×1
types ×1
volatility ×1
x86 ×1