C#学习教程:在C#下使用Int64对32位处理器是危险的原语操作;也就是说,该操作不是线程安全的。这意味着如果两个人同时给一个静态的Int64字段赋值,那么这个字段的最终值是无法预测的。三部分问题:这不是您遇到的每个变量。如果变量用作共享状态或其他东西(包括但不限于某些静态字段),您应该意识到这一点。由于在闭包或迭代器转换中关闭而未提升的局部变量非常好,并且一次由单个函数(因此,单个线程)使用。即使写入是原始的,您仍??然需要在访问变量时取出锁。如果不这样做,则至少必须使变量变为易变的,以确保所有线程在下次读取该变量时都能看到新值(这几乎总是您想要的)。这让你可以做原始的、可变的集合——但是一旦你想做一些更有趣的事情,比如给它加5,你就会被锁定。无锁编程非常非常难正确。您需要确切地知道您在做什么,并将复杂性保持在尽可能小的代码片段中。就我个人而言,我什至很少尝试它,除了非常知名的模式,例如使用静态初始化程序来初始化一个集合,然后在不锁定的情况下从中读取。在某些情况下,使用Interlocked类会有所帮助,但锁定它几乎总是容易得多。无可争议的锁是“非常便宜”的(诚然,它们会随着内核的增加而变得昂贵,但一切都是如此)——除非你有充分的证据证明它确实产生了重大影响,否则不要乱用无锁代码。MSDN:分配此类型的实例在所有硬件平台上都不是线程安全的,因为实例的二进制表示可能太大而无法在单个原语操作中分配。而且:与任何其他类型一样,对包含此类实例的共享变量的读取和写入必须由锁保护才能线程安全。如果你有一个共享变量(比如,作为一个类的静态字段,或者作为一个共享对象的字段),并且该字段或对象将被跨线程使用,那么,是的,你需要确保访问该变量通过原语操作受到保护。x86处理器具有确保这种情况发生的内在函数,并且此功能通过System.Threading.Interlocked类方法公开。例如:classProgram{publicstaticInt64UnsafeSharedData;公共静态Int64SafeSharedData;staticvoidMain(string[]args){ActionunsafeAdd=i=>{UnsafeSharedData+=i;};行动unsafeSubtract=i=>{UnsafeSharedData-=i;};动作safeAdd=i=>Interlocked.Add(refSafeSharedData,i);动作safeSubtract=i=>Interlocked.Add(refSafeSharedData,-i);WaitHandle[]waitHandles=new[]{newManualResetEvent(false),newManualResetEvent(false),newManualResetEvent(false),newManualResetEvent(false)};动作,对象>compute=(a,e)=>{for(Int32i=1;icompute(unsafeAdd,o),waitHandles[0]);ThreadPool.QueueUserWorkItem(o=>compute(unsafeSubtract,o),waitHandles[1]);ThreadPool.QueueUserWorkItem(o=>compute(safeAdd,o),waitHandles[2]);ThreadPool.QueueUserWorkItem(o=>compute(safeSubtract,o),waitHandles[3]);WaitHandle.WaitAll(waitHandles);Debug.WriteLine("不安全:"+UnsafeSharedData);Debug.WriteLine("安全:"+Saf电子共享数据);}}结果:不安全:-24050275641安全:0有趣的是,我在Vista64上以x64模式运行它,这表明64位字段在运行时被视为32位字段,即64位操作是non-primefaces。有谁知道这是CLR问题还是x64问题?在32位x86平台上,内存的最大基元大小为32位。这意味着如果某个东西写入或读取一个64位大小的变量,则该读取/写入可能会在执行期间被抢占。这只是32位平台上64位分配的可能竞争条件。然而,即使是32位变量,也可能存在读写条件,因此任何共享变量都应该以某种方式同步以解决这些竞争条件。这是真的吗?是的,事实证明。如果寄存器中只有32位,而需要将64位值存储到某个内存位置,则需要两次加载操作和两次存储操作。如果您的进程在这两个加载/存储之间被另一个进程中断,则另一个进程可能会损坏您一半的数据!奇怪但真实。这在构建的每个处理器上都是有问题的——如果你的数据类型比寄存器长,你就会遇到并发问题。这是我在现实世界中会担心的事情吗?是的,不。由于几乎所有的现代编程都有自己的地址空间,所以只有在进行多线程编程时才需要担心这一点。如果我的应用程序是多线程的,我真的需要用锁定代码包围我所有的Int64分配吗?遗憾的是,是的,如果您需要技术支持。事实上,在较大的代码块周围使用Mutex或Semaphore通常比将每个单独的set语句锁定在可全局访问的变量上更容易。以上是C#学习教程:在C#下使用Int64会对32位处理器造成危险。分享的所有内容,如果对大家有用,需要了解更多C#学习教程,希望大家多多关注——本文来自网络收藏,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
