java 原子地执行代码块
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16902224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
executing block of code atomically
提问by germantom
How would you answer the following question?
你会如何回答以下问题?
A method of a java class contains a block of code that must be executed atomically. Explain, using appropriate pseudo-code, how you would ensure that this block of code is executed atomically
java 类的方法包含必须以原子方式执行的代码块。使用适当的伪代码解释如何确保以原子方式执行此代码块
Would I achieve this by making the method ..
我会通过使方法实现这一点吗..
public final AtomicInteger x = new AtomicInteger(0);
then ensuring the get statement returned:
然后确保返回 get 语句:
x.get()
and if I wanted to increment the value of x would I do this?
如果我想增加 x 的值,我会这样做吗?
x.getAndIncrement();
回答by CPerkins
The answer depends on your definition of "atomic"
答案取决于你对“原子”的定义
I know of three valid definitions for atomic
:
我知道以下三个有效定义atomic
:
- Atomic as in synchronized: only one thread can be executing the code at one time;
- Atomic as in ACID: all of the action/block happens, or none of it does;
- Atomic as in uninterruptible: once the block starts, it can't be interrupted, even by task switching.
- 同步中的原子性:一次只能有一个线程执行代码;
- ACID 中的原子性:所有动作/块都发生,或者都不发生;
- 不可中断的原子性:一旦块开始,它就不能被中断,即使是通过任务切换。
The first is probably what your professor meant, and it's pretty easy to accomplish (see below).
第一个可能是你教授的意思,而且很容易完成(见下文)。
The second (atomic as in ACID) can be approximated. See below.
第二个(如 ACID 中的原子)可以近似。见下文。
The third simply cannot be guaranteed in Java - it doesn't provide access to the "critical sections" primitives required for uninterruptibility. Fortunately, the need for this is pretty much restricted to operating systems and device drivers.
第三个在 Java 中根本无法保证 - 它不提供对不间断性所需的“关键部分”原语的访问。幸运的是,对此的需求几乎仅限于操作系统和设备驱动程序。
Atomic as in synchronized
原子如同步
This is relatively straightforward: simply enclose your block of code in a synchronized block. I've shown it as a discrete block below, but there are other options:
这相对简单:只需将您的代码块包含在同步块中。我在下面将它显示为一个离散块,但还有其他选项:
public void doSomethingQuasiAtomic() {
synchronized (exampleLock) {
// Your code block goes here.
// Only one thread will ever be in this block at a time.
...
}
}
Atomic as in ACID
ACID 中的原子
There's no general-case solution for ACID
atomicity, but it can be approximated, also using synchronized code. In order to do this, each of the parts of the action must be safely reversible.
ACID
原子性没有通用的解决方案,但它可以被近似,也可以使用同步代码。为了做到这一点,动作的每个部分都必须是安全可逆的。
This is how I'd approach it:
这就是我的处理方式:
For the sake of argument, assume there's a multipart action you need to do on an object we'll call exampleObj
, that you have three actions to be performed which can be safelyreversed, and that all access to example
is synchronized on exampleLock
.
为了论证起见,假设您需要对我们将调用的对象执行多部分操作,您需要执行exampleObj
三个可以安全反转的操作,并且所有对 的访问都在example
上同步exampleLock
。
synchronized(exampleLock) {
boolean actionOneDone=false;
boolean actionTwoDone=false;
boolean actionThreeDone=false;
try {
actionOneDone=doActionOne(exampleObj); // or perhaps exampleObj.doActionOne();
if(actionOneDone) actionTwoDone=doActionTwo(exampleObj);
if(actionTwoDone) actionThreeDone=doActionThree(exampleObj);
} catch (Exception ex) {
// Whatever seems appropriate here.
} finally {
if (! (actionOneDone && actionTwoDone && actionThreeDone)) {
/* At least one part failed. Back out the completed actions in reverse order.
* Note that we never need to reverse action three since if it completed, so did the others.
*/
if (actionTwoDone) {
reverseActionTwo(exampleObj); // or perhaps exampleObj.reverseActionTwo();
}
if (actionOneDone) {
reverseActionOne(exampleObj);
}
}
}
}
回答by Mifeet
I believe that the expected answer was something like this:
我相信预期的答案是这样的:
public class A {
public void foo() {
// .. some code
doSomething(); // the critical part
// .. come code
}
public synchronized void doSomething() { // this is a synchronized method
// the critical code
}
}
The execution of doSomething()
is not really atomic (Disclaimer:it's very different from atomicity), but the synchronizedkeyword ensures that only one thread can enter the execution of this method (on one instance of A
). I think that is what they meant instead of atomicity.
的执行doSomething()
并不是真正的原子性(免责声明:它与原子性非常不同),但是synchronized关键字确保只有一个线程可以进入此方法的执行(在 的一个实例上A
)。我认为这就是他们的意思,而不是原子性。
Hereis another question about atomicity in Java. You may find something useful in there.
这是关于 Java 中原子性的另一个问题。你可能会在那里找到一些有用的东西。