18

您将如何回答以下问题?

java 类的方法包含必须以原子方式执行的代码块。使用适当的伪代码解释如何确保此代码块以原子方式执行

我会通过制作方法来实现这一点吗..

public final AtomicInteger x = new AtomicInteger(0);

然后确保返回 get 语句:

x.get()

如果我想增加 x 的值,我会这样做吗?

x.getAndIncrement();
4

2 回答 2

56

答案取决于您对“原子”的定义

我知道三个有效的定义atomic

  1. 同步中的原子:一次只能有一个线程执行代码;
  2. ACID 中的原子性:所有动作/块都发生,或者都不发生;
  3. 不可中断的原子:一旦块启动,它就不能被中断,即使是通过任务切换。

第一个可能是您教授的意思,而且很容易完成(见下文)。

第二个(在 ACID 中是原子的)可以近似。见下文。

第三个在 Java 中根本无法保证——它不提供对不间断所需的“关键部分”原语的访问。幸运的是,对此的需求几乎仅限于操作系统和设备驱动程序。

同步中的原子

这相对简单:只需将您的代码块包含在同步块中。我已将其显示为下面的离散块,但还有其他选项:

public void doSomethingQuasiAtomic() {
   synchronized (exampleLock) {
      // Your code block goes here. 
      // Only one thread will ever be in this block at a time.
      ...
   }
}

ACID 中的原子

原子性没有通用解决方案ACID,但它可以近似,也可以使用同步代码。为了做到这一点,动作的每个部分都必须是安全可逆的。

这就是我的处理方式:

为了争论,假设您需要对我们将调用的对象执行多部分操作,您需要执行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);
                }
            }
        }
    }
于 2013-06-03T21:35:48.990 回答
2

我相信预期的答案是这样的:

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
    }
}

的执行doSomething()并不是真正的原子(免责声明:它与原子性有很大不同),但同步关键字确保只有一个线程可以进入此方法的执行(在一个实例上A)。我认为这就是他们的意思,而不是原子性。

是另一个关于 Java 原子性的问题。你可能会在那里找到一些有用的东西。

于 2013-06-03T17:37:10.993 回答