2017-06-12 98 views
0

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

注意,在这种情况下,功能main可以开始10个线程(功能),并且每个这些10个线程的将接收的不可变参照同变量(在main定义)。但main函数仍然可以更改该共享变量的值。那么这会在并行/并行软件中造成问题吗?

我希望问题很清楚,但是让我知道如果不是。

P.S. “软件事务内存(STM)”能够解决潜在的问题吗?就像Clojure提供的一样?

+2

'main'与其他线程没有区别。因此,如果单个线程更改共享变量,则在所描述的情况下,您将拥有完全相同的多线程问题。 – 4386427

+1

@ 4386427注意到只有一个线程被允许写入内存的假设。所有其他线程只读...仍然有问题(我在写答案),但通常人们认为这有助于。 – Myst

+1

如果'main()'修改了变量,但是线程应该从中读取不同的值,那么您还没有解决问题。这可能是POSIX pthreads的一个问题。 'pthread_create()'函数接受一个'void *'最后一个参数,而一个常见的错误是传递一个循环控制变量的地址 - 这意味着线程无法知道它们将读取什么内容(值可能已经改变在函数被调用和线程启动之间)。 –

回答

2

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

NVIDIA forum,相对于GPU的操作,类似的问题是很整齐地回答:

当多个线程编写或从全局内存自然对齐位置读数/和数据类型是读或写的数据类型与所有线程相同,并且数据类型对应于支持的单指令线程访问类型之一...

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

我撇开那个线程可能会从CPU书读寄存器,而不是实际内存(忽略对数据的更新),这些大多是可以解决的使用volatile关键字C.

然而,冲突和记忆腐败仍然可能发生。

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

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

变量超过32位或64位时,将通常得到在时间(32位或64位)更新一个CPU“字”(不是OS字)。

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

+0

“软件事务内存(STM)”可以解决潜在的问题吗?就像Clojure提供的一样? – mahdix

+0

@mahdix - STM可能会保护你(因为日志和数据不适合,所以会执行回滚)......但这通常是一种语言功能。它可以在C中实现(可能是),但它只是一个替代使用锁...恕我直言,甚至不是一个很好的选择。 C不会自动执行STM的使用(如果你问我这个问题,它的目的就是击败它),所以你必须用STM逻辑来包围每一个读写操作。 – Myst

相关问题