0

練習のために、Java Synchronized キーワードを Java オブジェクトとして実装したいと思いました。以下のコードはこれに適した設計だと思いますか? AtomicReference は AtomicBoolean と同様のパフォーマンスを持つと思いますか?

提案後に更新されたコード:

public class SynchronizedBlock implements Runnable{

private final Lock lock;
private final Runnable runnable;

public SynchronizedBlock(Runnable r, Lock l){
    runnable = r;
    lock = l;
}

public void run() {
    try {
        while(!lock.compareAndSet(false, true)){
            Thread.sleep(100);
        }
        runnable.run();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }


}

 }

 public class Lock {
private final AtomicReference<Boolean> locked = new AtomicReference<Boolean>(false);

public boolean compareAndSet(boolean expected, boolean update){
    return locked.compareAndSet(expected, update);
}

public boolean isLocked(){
    return locked.get();
}

public void unlock(){
    locked.set(false);
}
 }

@Test
public void test() {



    final SynchronizedBlock sb = new SynchronizedBlock(new Runnable(){

        public void run() {
            x++;
            System.out.println(x);
        }

    }, new Lock());

    Runnable r1 = new Runnable(){

        int c = 0;
        public void run() {
            while(c<10){
                sb.run();
                c++;
            }
        }

    };

    Runnable r2 = new Runnable(){

        int c = 0;
        public void run() {
            while(c<10){
                sb.run();
                c++;
            }
        }

    };

    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();

    while (t1.isAlive() && t2.isAlive()){

    }

    assertEquals(20,x);

}
4

2 に答える 2

1

compareAndSwap をカプセル化するメソッドを追加する必要があります。ロックを取得する前に、ロックを解放するためにループしても意味がありません。ロックが空いているのに、ロックを解除しようとすると、ロックが解除されているという状況に陥るのはなぜですか。

ロック メソッドを削除し、ロック解除を最終ロックに配置して、例外/エラーによってロックが解除されないロックが発生しないようにします。

また、AtomicReference よりも自然な AtomicBoolean を使用します

于 2013-10-06T17:56:01.077 に答える
0

まず、最も重要なことは、 を削除する必要があることですThread.sleep(100)。これにより、2 スレッドの競合のみでも、少なくとも 100 ミリ秒の遅延が発生します。

AtomicBooleanコードを単純化するために代わりに使用できAtomicReferenceます。また、競合の多い状況での並行性が本当に心配な場合は、コードを変更して、CAS を実行する前にロックされているかどうかを確認できます。

while (true) {
  if (lock.isLocked()) continue; // or get() == true if you use AtomicBoolean
  if (lock.compareAndSet(false, true)) 
    break;
}

これは、ローカル スピンを利用してループ中のメイン メモリ アクセスを減らす TTAS (Test-Test-And-Set) ロックの例です。http://en.wikipedia.org/wiki/Test_and_Test-and-setを参照してください

于 2013-10-08T07:36:52.923 に答える