以原子方式执行代码块

时间:2013-06-03 17:15:58

标签: java thread-safety atomic

您如何回答以下问题?

  

java类的方法包含必须的代码块   原子地执行。使用适当的伪代码解释你的方式   将确保这个代码块以原子方式执行

我是否可以通过制作方法实现这一目标..

public final AtomicInteger x = new AtomicInteger(0);

然后确保返回get语句:

x.get()

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

x.getAndIncrement();

2 个答案:

答案 0 :(得分:39)

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

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

  1. 同步中的原子:一次只能有一个线程执行代码;
  2. ACID中的原子:所有的动作/阻止都会发生,或者都不会发生;
  3. Atomic as uninterruptible:一旦块启动,即使通过任务切换也不会中断。
  4. 第一个可能是你教授的意思,而且很容易实现(见下文)。

    第二个(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);
                    }
                }
            }
        }
    

答案 1 :(得分: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()的执行并非真正原子(免责声明:它与原子性非常不同),但synchronized关键字确保只有一个线程可以进入执行这个方法(在A的一个实例上)。我认为这就是他们的意思,而不是原子性。

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