是否可以使一段代码原子化(C#)?

16

当我说原子性时,我的意思是一组指令将在同一进程的其他线程之间没有上下文切换的情况下执行(当然还需要进行其他类型的切换)。我想到的唯一解决方案是在执行当前部分之前暂停除当前执行的线程外的所有线程,并在执行后恢复它们。还有更优雅的方法吗?

我想这么做的原因是收集多个线程上运行的对象的连贯状态。但是,它们的代码无法更改(它们已经编译好了),因此我无法在其中插入互斥量、信号量等。原子操作当然是状态收集(即拷贝某些变量)。


1
你想要达到什么目的?挂起所有其他线程是一种危险的做法,你可能会遇到死锁的情况,其中你唤醒的线程试图执行某些操作,而其中一个被挂起的线程持有某种类型的锁,它永远无法释放。 - Roger Perkins
我从未听说过原子这个词在这个上下文中的使用。我只知道它作为ACID的一部分,即事务的定义。顺便问一下,你为什么需要这个? - Stefan Steinegger
单个IL操作是原子性的。 只有很少的类(其中之一是Interlocked)支持原子操作。 除此之外,没有其他的。 而且我不认为这有什么意义。 - user47589
1
@yodaj007:并不是所有的IL操作都是原子操作。例如,在32位主机上存储或获取long/ulong/double就不是原子操作。 - cdhowie
@cdhowie,啊,对了。我向你的智慧致敬。 - user47589
@Roger,Stefan,yodaj007:我试图详细说明原因。 - konrad.kruczynski
5个回答

6
Interlocked类中有一些原子操作,但它只提供了一些非常简单的操作。它不能用于创建整个原子代码块。
我建议小心使用锁定,以确保您的代码即使上下文发生变化也能正常工作。

1
不可以。你可以使用 Monitor 来包装一段代码块,使其线程安全,但你不能将一般的代码片段变成原子操作。
object lck = new object();

lock(lck)
{
     // thread safe code goes in here

}

为什么这被踩了?我的回答有什么错误吗? - user47589
@yodaj007:不是我给你点了踩,但我猜测原因可能是:如果你盲目地复制和粘贴代码,每次运行它都会创建一个新的对象,因此实际上不会同步任何内容。 - Mark Byers
唉,是的,我打的就是这样。虽然不是盲目地复制/粘贴。我是在Notepad++中打的。 - user47589
@Mark:即使他将其作为静态成员变量,问题仍然是如何回到旧的DOS时代,将所有CPU时间都用于某些指令。所以他没有读懂问题,我也投了反对票。但我现在会把它移除。 - Xaqron
@Xaqron:大体上是这样,然而主要的想法是让其他线程不要干扰正在收集的数据。其他线程和属于另一个进程的所有线程都可以自由地接管CPU :) - konrad.kruczynski
@MarkByers 但是为什么每次都会创建一个新对象呢?起初,我认为lck应该是静态的,但是后来我看了http://msdn.microsoft.com/en-us/library/ms173179.aspx和http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx,所以Amy的方法似乎是合法的。不知道为什么答案被踩了。 - Vitalii Vasylenko

1

嗯,你可以使用,但你不能确切地防止上下文切换。但是,如果你的线程在相同的对象上加锁,那么等待的线程显然不会运行,因为没有东西可运行,所以就没有涉及到上下文切换。

你可能还想看看这个页面


锁并不一定会“在同一进程的另一个线程上没有任何上下文切换”的情况下被使用。 - Logan Capaldo
是的,我后来意识到了;做了一点小改动,但我想它仍然没有很好地回答问题。 - user541686

0

不,那是违反多任务处理的原则。

除非是非常简单的操作,比如增量操作……这些并不是你问题的重点。


1
递增一个数字也不是原子操作,除非你在谈论Interlocked类。如果需要,我可以提供代码进行演示;在SO上提出问题,我会回答它。 - user47589
我谈到了一般性的话题,简单操作就像 Interlocked.Increment() 等等。 - Xaqron

0

可以通过由原子单读/多写寄存器集合(数组)组成的共享内存获取全局状态。解决方案简单但不平凡。您可以阅读论文“共享内存的原子快照”中发布的算法,或者阅读多处理器编程艺术书的第4章,在那里您可以获得有关Java语言实现的想法。当然,一旦您熟悉了这个想法,就应该能够将其传输到任何其他语言。如果我的英语不够好,请见谅。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接