以原子方式执行代码块

ger*_*tom 10 java atomic thread-safety

你会如何回答以下问题?

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

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

public final AtomicInteger x = new AtomicInteger(0);
Run Code Online (Sandbox Code Playgroud)

然后确保返回get语句:

x.get()
Run Code Online (Sandbox Code Playgroud)

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

x.getAndIncrement();
Run Code Online (Sandbox Code Playgroud)

CPe*_*ins 45

答案取决于你对"原子"的定义

我知道三个有效的定义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.
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

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);
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 关于 Atomic 和 ACID 我会添加 if (actionOneDone) actionTwoDone=... 并且对于动作三也是如此。否则,您必须对所有三个动作进行反向操作。此外,如果一项操作失败,您无需尝试其他操作。总的来说,我喜欢这种非常普遍的表述。我现在正在现实生活中解决这个任务,我只想到了更具体的解决方案。+1。 (2认同)