同期とReentrantLockの違いを知っている必要があります、かどうかを知るための知識がありません

アプリケーション開発では、常にシーンをロックするための方法の必要性を満たす、Javaは1が同期され、ロックに私たちのために二つの方法を提供し、第二には、ロックモードです。だから、実際の開発では、我々はそれがロック何を意味するのか選択する必要があります

EDITORIAL

この記事を読むことによって、あなたは学ぶことができます:

  • ReentrantLockの異なると同期して、同じポイント
  • ReentrantLockの、同期した割り込み応答テスト
  • ReentrantLockの#のtryLockタイミングは、ロックのテストを取得します
  • ReentrantLockのフェアロック、ロック不公平テスト
  • ReentrantLockのと同期したパフォーマンステスト
  • ReentrantLockのシナリオが導入します

同じポイント

  • 独占=>一つだけのスレッドがロックを獲得します
  • 別のスレッドにすぐ見える共有変数のメモリ可視性=>変更
  • リエントラント=>同じスレッドが(同じロックオブジェクトまたはオブジェクトクラスを有することを条件とする)の外層、内層と、このスレッドの方法には、自動的にロックを取得する場合、方法のロックを取得し、以前介して取得されていないませんリリースブロックされました

異なる点

ロック 同期 ReentrantLockの
ロックはロックモードを解除します ユーザーのケア、オートロックを必要としない、ロックが解除されます 明示的なロックは、ロックが解除され、それは、ロックを取得するためにロックメソッドを呼び出してロック解除方法のリリースにロックを呼び出す必要があります
割り込み ない割り込み応答 割り込み応答
タイムアウト獲得ロック 許可されていません 許します
フェアロックすることができます いいえ、それは非デフォルトのフェアロックであります ロック公正、非デフォルトのフェアロックに入ってくる真の公正をロックするかどうか、コンストラクタで指定されています
実装 JVMレベル APIレベル

同期と比較してReentrantLockのより柔軟

ReentrantLockの試験方法

ロックReentrantLockのインターフェースが実装されるインタフェースロック方法で定義されたクラス:

  • 空ロック()=>すぐにロックを獲得
  • tryLock(ブール値)=>直ちにロックを獲得
  • tryLockブール値(長い時間、TimeUnitでユニット)InterruptedExceptionある=>ロックを取得するために、指定された時間内に、ロックが真のリターンを得られるスロー、ロック返し偽を得ません
  • 空lockInterruptibly()InterruptedExceptionある=>割り込みロック取得をスローします
  • 空ロック解除()=>リリースロック
  • 条件newCondition()=>戻る条件インスタンスは、このロックのインスタンスにバインドされています

tryLockロック戻り値以外の方法が同じではない、ロックが割り込みに応答して取得することができない、しかしのtryLockロックが割り込みを取得するロック。添加のtryLockの方法(長い時間、TimeUnitで単位)ロックのみロック方法をロックするロックを獲得するために、すなわち、割り込みに応答して取得された割り込みに応答して取得されていません

割り込みに応答lockInterruptibly:ReentrantLockLockInterruptiblyTest.java

public class ReentrantLockLockInterruptiblyTest {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Task());
        thread.start();
        Thread.sleep(3 * 1000);  //执行三秒后中断线程
        thread.interrupt();
    }

    public static class Task implements Runnable {
        Lock lock = new ReentrantLock();

        public Task () {
            new Thread(() -> {
                try {
                    lockMethod();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        @Override
        public void run() {
            try {
                lockMethod();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("End...");
        }

        private void lockMethod() throws InterruptedException {
            lock.lockInterruptibly();
            try {
                //模拟长时间不释放锁
                while (true) {}
            } finally {
                lock.unlock();
            }
        }
    }
}
复制代码

結果:

java.lang.InterruptedException
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
	at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
	at com.h2t.study.concurrent.lock.ReentrantLockLockInterruptiblyTest$Task.lockMethod(ReentrantLockLockInterruptiblyTest.java:45)
	at com.h2t.study.concurrent.lock.ReentrantLockLockInterruptiblyTest$Task.run(ReentrantLockLockInterruptiblyTest.java:37)
	at java.lang.Thread.run(Thread.java:748)
End...
复制代码

割り込み成功

割り込みに同期応答:SynchronizedBlock.java

public class SynchronizedBlock {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Task());
        thread.start();
        Thread.sleep(3 * 1000);  //执行三秒后中断线程
        thread.interrupt();
        System.out.println(thread.isInterrupted());
    }

    public static class Task implements Runnable {
        public Task() {
            new Thread() {
                public void run() {
                    f();
                }
            }.start();
        }

        public synchronized void f() {
            while (true) {
            }
        }

        @Override
        public void run() {
            f();
            System.out.println("End");
        }
    }
}
复制代码

コンソールは、エンドプリントアウトし、例外をスローすることはありません
スレッドがロックを待機中である場合、スレッドの割り込み通話が割り込みに応答していない有効になりません、同期のために。ロックは、応答を中断することができます

tryLock時間ロック:ReentrantLockTryLockTest.java

public class ReentrantLockTryLockTest {
    public static void main(String[] args) {
        ExecutorService es = Executors.newCachedThreadPool();
        for (int i = 0; i < 2; i++) {
            es.execute(new Task(i));
        }
    }

    private static class Task implements Runnable {
        private static Lock lock = new ReentrantLock();

        private int i;

        public Task(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            try {
                lockMethod();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //每次只允许一个线程调用
        private void lockMethod() throws InterruptedException {
            long start = System.currentTimeMillis();
            //2s内获得锁
            if (lock.tryLock(2, TimeUnit.SECONDS)) {
                System.out.println(String.format("i = %d 获取到锁,耗时:%d", i, System.currentTimeMillis() - start));
                try {
                    Thread.sleep(1000 * 60 * 1);  //睡眠1分钟
                } finally {
                    lock.unlock();
                }

            } else {
                System.out.println(String.format("i = %d 获取到锁失败,耗时:%d", i, System.currentTimeMillis() - start));
            }
        }
    }
}
复制代码

実行方法は、2秒以内にロックが実行される結果を得るための方法の試みをロック、ロックのメソッドを呼び出します。

i = 0 获取到锁,耗时:0
i = 1 获取到锁失败,耗时:2001
复制代码

ReentrantLockのフェアロックと非ロックフェア:ReentrantLockFairTest.java

public class ReentrantLockFairTest {
    //通过传入true创建一个公平锁
    private static Lock fairLock = new ReentrantLock(true);
    //非公平锁,默认为非公平锁
    private static Lock unfairLock = new ReentrantLock();

    public static void main(String[] args) {
        ExecutorService unfairEs = Executors.newCachedThreadPool();
        ExecutorService fairEs = Executors.newCachedThreadPool();

        for (int i = 0; i < 5; i++) {
            unfairEs.execute(new UnfairTask(i));
            fairEs.execute(new FairTask(i));
        }
    }

    /**
     * 非公平锁任务
     * */
    private static class UnfairTask implements Runnable {
        private int i;

        public UnfairTask(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            unfairLock.lock();
            try {
                System.out.println(String.format("unfairTask i = %d is running", i));
            } finally {
                unfairLock.unlock();
            }
        }
    }

    /**
     * 公平锁任务
     * */
    private static class FairTask implements Runnable {
        private int i;

        public FairTask(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            fairLock.lock();
            try {
                System.out.println(String.format("fairTask i = %d is running", i));
            } finally {
                fairLock.unlock();
            }
        }
    }
}
复制代码

結果:

unfairTask i = 0 is running
fairTask i = 0 is running
unfairTask i = 1 is running
fairTask i = 1 is running
unfairTask i = 2 is running
fairTask i = 3 is running
unfairTask i = 3 is running
fairTask i = 2 is running
fairTask i = 4 is running
unfairTask i = 4 is running
复制代码

フェアロック先着、実行の順序を注文されるように。結果は順不同実行順序になるよう、後でちょうどロックから抜け出す提出スレッドは、実行前にロックを解除する場合はアンフェアロック

同期不公平ロック:

public class SynchronizedUnfairTest {
    public static void main(String[] args) {
        ExecutorService unfairEs = Executors.newCachedThreadPool();

        for (int i = 0; i < 5; i++) {
            unfairEs.execute(new UnfairTask(i));
        }
    }

    /**
     * 非公平锁任务
     * */
    private static class UnfairTask implements Runnable {
        private int i;

        public UnfairTask(int i) {
            this.i = i;
        }

        @Override
        public synchronized void run() {
            System.out.println(String.format("unfairTask i = %d is running", i));
        }
    }
}
复制代码

結果:

unfairTask i = 1 is running
unfairTask i = 0 is running
unfairTask i = 3 is running
unfairTask i = 2 is running
unfairTask i = 4 is running
复制代码

デフォルトの非同期ロック公正、公平な、そして唯一の非ロック、したがって、シーケンスの結果が乱れています

性能試験

ReentrantLockのロックタスク:ReentrantLockTask.java

public class ReentrantLockTask implements Runnable {
    private int i;

    public ReentrantLockTask(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        lockMethod();
    }

    ReentrantLock lock = new ReentrantLock();
    private void lockMethod() {
        int sum = 0;
        lock.lock();
        try {
            for (int j = 0; j < 10; j++) {
                sum += j;
            }

        } finally {
            lock.unlock();
        }
    }
}
复制代码

同期ロッキングタスク:SynchronizedLockTask.java

public class SynchronizedLockTask implements Runnable {
    private int i;

    public SynchronizedLockTask(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        lockMethod();
    }

    private synchronized void lockMethod() {
        int sum = 0;

        for (int j = 0; j < 10; j++) {
            sum += j;
        }
    }
}
复制代码

テストカテゴリ:PerformTest

public class PerformTest {
    public static void main(String[] args) {
        for (int i = 100; i < 1000000000; i = i * 10) {
            reentrantLockTest(i);
            synchronizedLockTest(i);
        }
    }

    /**
     * 循环执行的次数
     * */
    private static void reentrantLockTest(int time) {
        ExecutorService es = Executors.newCachedThreadPool();
        long start = System.currentTimeMillis();
        for (int i = 0; i < time; i++) {
            es.execute(new ReentrantLockTask(i));
        }

        System.out.println(String.format("ReentrantLockTest time = %d Spend %d", time, System.currentTimeMillis() - start));
    }

    private static void synchronizedLockTest(int time) {
        ExecutorService es = Executors.newCachedThreadPool();
        long start = System.currentTimeMillis();
        for (int i = 0; i < time; i++) {
            es.execute(new SynchronizedLockTask(i));
        }

        System.out.println(String.format("SynchronizedLockTest time = %d Spend %d", time, System.currentTimeMillis() - start));
    }
}
复制代码

サイクルタスク、統計的なサイクルの時間のかかる作業

テスト結果:

ReentrantLockTest time = 100 Spend 6
SynchronizedLockTest time = 100 Spend 2
ReentrantLockTest time = 1000 Spend 7
SynchronizedLockTest time = 1000 Spend 14
ReentrantLockTest time = 10000 Spend 42
SynchronizedLockTest time = 10000 Spend 29
ReentrantLockTest time = 100000 Spend 186
SynchronizedLockTest time = 100000 Spend 156
ReentrantLockTest time = 1000000 Spend 1428
SynchronizedLockTest time = 1000000 Spend 1006
ReentrantLockTest time = 10000000 Spend 9716
SynchronizedLockTest time = 10000000 Spend 9791
ReentrantLockTest time = 100000000 Spend 97928
SynchronizedLockTest time = 100000000 Spend 99804
复制代码

同期と性能のReentrantLockの以下、良いとの悪い方教えて

同期とReentrantLockの間で選択する方法

ほぼ同期とReentrantLockの性能は、とReentrantLockのを使用して飽くことのないシーンを同期した場合にのみとき ReentrantLockのニーズが明示的にロックを解除するため、およびJVMレベルを同期、JVMを最適化することができ、かつリエントラントは何のAPIレベルではありません任意の最適化。同期飽くなきシナリオ:

  • タイミング取得のロック
  • 割り込み応答
  • 私たちは、公正な方法でロックを取得する必要があります

最終添付ファイル:サンプルコード
ようこそフォークを持つ

添付の過去の記事:あなたが読むことを歓迎している、親指、コメント

同時は、関連する
エグゼキュータは、スレッドプールを作成無効にするには1.なぜアリババの?
2.自分のこと、例外処理スレッドを行います

デザインパターン関連: 1.シングルトン、あなたが本当にそれを書くのか? 2.(+工場モデル戦略モード+マップ)キルプロジェクトのスイッチケースをパッケージ化

JAVA8関連: 1.ストリームAPI最適化されたコード のプロ2、あなたがLocalDateTimeをああ日の代わりに使用することをお勧めします

データベース関連: クエリ効率1. mysqlデータベース時間のdatetime型、BIGINT、タイムスタンプ比較 2.'m嬉しいです!最後にゆっくりとピットクエリを踏ん

効率的な関連: 1のラインとJavaの足場、統一されたプロジェクトチームの構造のスタイル

ログイン関連: 1.ログフレームは、LogbackまたはLog4j2を選択しますか? 2. Logbackプロファイルそう書かれ、10回TPS

プロジェクトが関連する: 1.何もない、ハンズオンLRUローカルキャッシュを書い 2のRedisは親指の機能モジュール達成 3. JMX視覚的な監視スレッドプール 4.著作権管理[SpringSecurity記事] マスターへのエントリから5.春のカスタムアノテーションを 6 。Javaは着陸Youkuのシミュレートされた 高いので、それはマルチレベルキャッシュバー書くことであろう7 QPSを スクリーンショットphantomjsを使用して8 javaの

その他: 1.のtry-と資源優雅近いリソース 2.ボス、なぜべきである私の賃金控除フロートとストレージの量

おすすめ

転載: juejin.im/post/5ddd2a7c6fb9a0717b5fce02