如果我们只允许局部变量是可变的,我们可以阻止共享的可变状态吗?

时间:2017-06-12 17:31:23

标签: c multithreading concurrency clojure immutability

在非OOP编程语言中,如C,如果我们只允许局部变量以各种可能的方式进行变异(更改内部字段,重新分配,......)但不允许变异函数参数,它会帮助吗我们阻止共享的可变状态?

注意,在这种情况下,函数main可以启动10个线程(函数),并且这10个线程中的每一个都将接收对同一变量的不可变引用(在main中定义)。但main函数仍然可以更改该共享变量的值。那么这会导致并发/并行软件出现问题吗?

我希望问题很明确,但如果不是,请告诉我。

P.S。 “软件事务存储器(STM)”可以解决潜在的问题吗?就像Clojure提供的那样?

1 个答案:

答案 0 :(得分:2)

是和否......这取决于平台,CPU,共享变量的大小和编译器。

NVIDIA forum上,就GPU操作而言,类似的问题得到了非常巧妙的回答:

  

当多个线程在全局内存中写入或读取自然对齐位置时,所有线程读取或写入的数据类型相同,并且数据类型对应于单指令线程支持的类型之一访问...

(许多GPU单指令在事先知道时可处理16字节字(128位),但大多数CPU使用单指令32位或64位限制)

我撇开线程可能从CPU寄存器而不是实际内存中读取的机会(忽略对数据的更新),这些通常使用C中的volatile关键字来解决。

但是,冲突和内存损坏仍然可能发生。

某些内存存储操作由内部(由CPU)或编译器(机器代码)使用大量存储调用处理。

在这些情况下,主要是在多核机器上(但不仅仅是),有“读者”和“#34;读者”的风险。将收到部分更新的信息,并且没有任何意义(即指针的一半是有效的而另一个是没有的。)

大于32位或64位的变量,通常会更新CPU" word" (不是OS字)一次(32位或64位)。

字节大小的变量是超级安全的,这就是为什么它们经常被用作标志......但它们应该可以使用操作系统或编译器提供的atomic_*存储/写入操作来处理