感谢您的评论。
答案 0 :(得分:14)
我会推动您的同事获取数据或至少引用。
问题是,如果您有共享数据,那么您就拥有了共享数据。无论是通过静态类,单例,还是其他方式暴露,都不是非常重要。如果您首先不需要共享数据,我希望您不会有静态类。
除此之外,在任何给定的应用程序中,静态类中的共享数据的处理器缓存可能存在更大的瓶颈。
与以往一样,首先编写最明智,最易读,最易维护的代码 - 如果遇到性能瓶颈并采取相应措施,请确定代码。
答案 1 :(得分:3)
“[a]静态实例无法在处理器缓存之间共享。是吗?”
这句话对我来说没什么意义。每个处理器的专用缓存的要点是它包含一小块内存的私有副本,因此如果处理器正在执行一些只需要访问该特定内存区域的算法,那么它就不必继续回来访问外部存储器。如果我们讨论静态类中的静态字段,那些字段的内存可能都适合连续的内存块,而后者又适合单个处理器(或内核)的专用缓存。但是它们每个都有自己的缓存副本 - 它不是“共享”的。这就是缓存的重点。
如果算法的工作集大于缓存,那么它将击败该缓存。这意味着当算法运行时,它会重复使处理器从外部存储器中提取数据,因为所有必需的部分都不会立即适合缓存。但这是一个普遍的问题,不适用于静态类。
我想知道你的同事实际上是在谈论性能,而是在多个线程正在读/写相同数据时是否需要应用正确的锁定?
答案 2 :(得分:3)
如果多个线程正在写入到该数据,则会有缓存抖动(一个CPU缓存上的写入会使其他CPU的缓存无效)。你的朋友技术上是正确的,但很有可能它不是你的主要瓶颈,所以没关系。
如果多个线程正在读取数据,那么您的朋友就会出现问题。
答案 3 :(得分:2)
如果您不使用任何类型的锁或同步,则静态与非静态不会对您的性能产生任何影响。
如果您正在使用同步,那么如果所有线程都需要获取相同的锁,则可能会遇到问题,但这只是静态的副作用,而不是方法静态的直接结果。 / p>
答案 4 :(得分:2)
在任何“虚拟机”控制语言(.NET,Java等)中,此控件可能会委托给底层操作系统,并可能进一步下载到BIOS和其他调度控件。话虽如此,在.NET和Java这两个大问题中,静态与非静态是内存问题,而不是CPU问题。
重新讨论saua的观点,对CPU的影响来自同步和线程控制,而不是对静态信息的访问。
CPU缓存管理的问题不仅限于静态方法。一次只能有一个CPU可以更新任何内存地址。虚拟机中的对象,特别是对象中的字段,是指向所述内存地址的指针。因此,即使我有一个可变对象Foo
,在Foo上调用setBar(true)
一次只允许在一个CPU上。
所有这一切,.NET和Java的关键在于你不应该把时间花在讨论这些问题上,直到你能证明你有问题并且我怀疑你会这样做。
答案 5 :(得分:1)
因此:
在设计高度多线程的应用程序时,请尝试使用许多细粒度的锁。分割你的数据,以便一个线程可以抓取一个并运行它,希望没有其他线程需要等待它,因为他们忙于自己的数据。
答案 6 :(得分:1)
x86架构实现了缓存侦听,以便在写入时保持数据缓存同步,如果它们碰巧缓存相同的东西......并非所有架构都在硬件中执行此操作,有些架构依赖于软件来确保案例永远不会发生。 / p>
答案 7 :(得分:0)
即使这是真的,我怀疑你有很多更好的方法来提高性能。当它将静态更改为实例时,对于处理器缓存,你会知道你真的在推动它的发展。