web-dev-qa-db-ja.com

コードのブロックをアトミックに実行する

次の質問にどのように答えますか?

Javaクラスのメソッドには、アトミックに実行する必要のあるコードのブロックが含まれています。適切な擬似コードを使用して、このコードのブロックがアトミックに実行されるようにする方法を説明してください。

メソッドを作成することでこれを達成できますか..

public final AtomicInteger x = new AtomicInteger(0);

次に、getステートメントが返されることを確認します。

x.get()

xの値をインクリメントしたい場合は、これを実行しますか?

x.getAndIncrement();
13
germantom

答えは「アトミック」の定義によって異なります

atomicの3つの有効な定義を知っています。

  1. 同期の場合と同様にアトミック:一度に1つのスレッドのみがコードを実行できます。
  2. ACIDの場合と同様にアトミック:すべてのアクション/ブロックが発生するか、発生しない。
  3. 無停電の場合と同様にアトミック:ブロックが開始されると、タスクの切り替えによっても中断することはできません。

最初はおそらくあなたの教授が意味したことであり、それは非常に簡単に達成できます(以下を参照)。

2番目(ACIDのように原子)は概算できます。下記参照。

3番目は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と呼ぶオブジェクトに対して実行する必要のあるマルチパートアクションがあると仮定します。実行するアクションは3つあり、安全に実行できます。 が逆になり、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);
                }
            }
        }
    }
49
CPerkins

期待される答えは次のようなものだったと思います。

_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()の実行は実際にはアトミックではありません(免責事項:アトミック性とは大きく異なります)が、 同期 キーワードは、1つのスレッドのみがこのメソッドの実行に入ることができることを保証します(Aの1つのインスタンスで)。それが原子性の代わりに彼らが意味したことだと思います。

ここ はJavaの原子性に関する別の質問です。あなたはそこに何か役に立つものを見つけるかもしれません。

2
Mifeet