Java同時実行時の反発ロックメカニズム

5212 ワード

一、二種類の反発機構


Javaは、リソースの共有時に存在する同時問題を解決するために2つの反発ロックを提供します.
1つの方法はsynchronizedキーワードを提供することであり、タスクがsynchronizedキーワードによって保護されたコードフラグメントを実行するときに使用可能であることを確認し、ロックを取得し、コードを実行し、ロックを解放する.
もう1つの方法は、Java SE 5のjavaでロックオブジェクトを明示的に使用することである.util.concurrent.locksクラスライブラリでは、このオブジェクトが定義されています.ロックオブジェクトは明示的に作成され、ロックされ、解放される必要があります.次の例では、3つのスレッドの同時アクセスタスクを作成し、タスクに99-1の数字を出力し、効果を達成するために出力する前にスレッドを100 ms寝させた2つのロックメカニズムの違いを体験します.
synchronized同期コード方式:
public class SynchronizedTest {
    public static void main(String[] args) {
        LockDemo2 demo2 = new LockDemo2();
        new Thread(demo2," ").start();
        new Thread(demo2," ").start();
        new Thread(demo2," ").start();
    }
}
class LockDemo2 implements Runnable{
    private int num = 100;

    @Override
    public void run() {
        while(true){
            synchronized(this){
                if(num > 1){
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName()+" :" + --num);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}

明示ロック方式:
public class LockTest {
    public static void main(String[] args) {

        LockDemo demo = new LockDemo();
        new Thread(demo," ").start();
        new Thread(demo," ").start();
        new Thread(demo," ").start();
    }
}

class LockDemo implements Runnable{
    private int num = 100;
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while(true){
            lock.lock();
            try {
                if(num > 1){
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName()+" :" + --num);
                }else{
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
}

二、対比


上記の2つの方法は、同時実行時に共有リソースを解決する問題を解決することができますが、この2つの方法はどのような違いがありますか?
synchronizedメソッドまたは文の使用は、各オブジェクトに関連する暗黙的なモニタロックへのアクセスを提供しますが、すべてのロックの取得と解放を1つのブロック構造に強制します.複数のロックが取得された場合、それらは逆の順序で解放され、すべてのロックが取得された場合と同じ語法範囲ですべてのロックを解放する必要があります.また、ロックの明示的なロック方式で書かれたコードよりも優雅ですが、ノードAのロックを取得し、ノードBのロックを取得し、Aを解放してCを取得し、Bを解放してDを取得するなど、いくつかの問題を解決する際にロックの柔軟性に及ばないことがあります.
ロック明示ロックは前述したようにsynchronizedよりも柔軟であり、時には特殊な問題を解決することがある.ロックを使用するときは、ロックを追加した後にロックを解除することに注意してください.ロックが解放されるように、unlock()メソッドをfinally文ブロックに定義する必要があります.これにより、コード同期中にエラーが発生した場合、finally句でエラーを維持できるという利点もあります.ロックの実装クラスには強力な機能もたくさん用意されているので、後で書きましょう.