LoginSignup
16
12

More than 5 years have passed since last update.

ReentrantLockで順序性を保証するロック

Last updated at Posted at 2018-05-26

個人用メモ。
Javaの排他制御について調べていたところ、以下の記事を見つけました。
Javaのsynchronizedは順序を保証しない。
記事中で言及されているように、synchronizedによるロックは、複数同時にロックした場合の解放順序を保証しません。
理解していないと、ひょんなところでドはまりしそうです(しました)。
当方の対処としては、ロック機構をsynchronizedからjava.util.concurrent.locks.ReentrantLockに置き換えました。

ReentrantLockを使う

// コンストラクタはfair=trueで指定する
// lockインスタンスは排他制御するスレッド間で使いまわす
ReentrantLock lock = new ReentrantLock(true);
try {
    lock.lock();
    // 排他制御中の処理
} finally {
    lock.unlock();
}

ロックの取得と解放を自動化する

そのまま使用しても目的は果たせるのですが。synchronizedと違い明示的なロック解放が必要な分、うっかり漏れると、深刻な状況になりかねません。
そこで、ReentrantLockのラッパーを作成し、ロックとアンロックをペアで使用することを強制しました。

FairLock.java
public class FairLock {
    private ReentrantLock lock = new ReentrantLock(true);

    public void withSync(FairSyncTask task) {
        try {
            lock.lock();
            task.act();
        } finally {
            lock.unlock();
        }
    }

    public interface FairSyncTask {
        void act();
    }
}
使用例
// synchronizedで書いていた例
private final Object syncObj = new Object();

public void actWithUnfair() {
    synchronized(syncObj) {
        // 排他制御中の処理
    }
}

// ReentrantLockのラッパーで置き換えた例
private final FairLock fairLock = new FairLock();

public void actWithFair() {
    fairLock.withSync(() -> {
        // 排他制御中の処理
    });
}

まとめ

知っていればなんてことないのでしょうが。
この記事が誰かの助けになれば幸いです。

16
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
12