2013-06-03 46 views
5

你会如何回答以下问题?以原子方式执行代码块

java类的方法包含一个代码块,它必须是原子执行的 。说明一下,使用合适的伪代码,你怎么 会确保代码块被自动执行

我会通过使该方法达到这个..

public final AtomicInteger x = new AtomicInteger(0); 

然后确保返回的GET语句:

x.get() 

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

x.getAndIncrement(); 
+3

在原子上相对于什么? – SLaks

+0

抱歉,我不确定,这是我们所有的问题。这是一个过去的考试问题,我们还没有给出答案的例子 – germantom

+1

这个问题太模糊,无法回答。 – SLaks

回答

32

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

我知道的三个有效的定义为atomic

  1. 原子作为同步的:只有一个线程可以在一个被执行代码时间;
  2. 原子和ACID一样:所有的动作/阻挡发生,或者没有一个;
  3. 不可中断的原子:一旦块启动,即使通过任务切换也不会中断。

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

第二个(原子和ACID一样)可以近似。见下文。

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

原子作为同步

这是相对比较简单:只需附上的代码块中的一个synchronized块。我已经展示了它作为下方的一个独立块,但也有其他的选择:

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(); 
      actionTwoDone=doActionTwo(exampleObj); 
      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); 
       } 
      } 
     } 
    } 
+0

有趣!我只是把自己看作是一个测试答案:P – Mifeet

+0

好吧,先生!清晰简洁。 –

1

我认为,预期的答案是这样的:

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()的执行是不是真的原子(免责声明:这是从原子非常不同),但synchronized关键字保证只有一个线程可以输入此方法的执行(在A的一个实例中)。我认为这是他们的意思,而不是原子性。

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

+1

这与原子性非常不同。其他函数仍然可以观察处于不一致状态的对象。 – SLaks

+1

这可能是这个问题提到的问题,但“同步”方法绝不保证原子性。 –

+1

是的,但这个问题显然没有意义,所以我认为它只是表达不佳。我认为它们意味着原子性,即在“原子”块中交叉指令被排除。我知道这不是真正的原子性,但他们谈论“代码块”,所以他们可能甚至不指AtomicInteger或任何东西。 – Mifeet