注目記事

【Javaコード入門】スレッド_③ReentrantLockクラス

明示的にロックを獲得する – ReentrantLockクラス

public void lock()
public void unlock()

synchronizedブロックによる同期は、アプリ開発者がロックの獲得/解除を意識しなくても良いことから「暗黙的なロック」と呼ばれます。対して、メソッドを跨る処理などで「明示的に」ロックを獲得/解除したい場合があります。この場合、ReentrantLockクラス(java.util.concurrent.locksパッケージ)を利用します。
ReentrantLockクラスではlockメソッドで明示的にロックを獲得した後、unlockメソッドで解除する必要があります。
以下は、synchronized修飾子の項のサンプル(incrementメソッド)をReentrantLockクラスで書き換えたものです。

LockSample.java
  1. package com.example.mynavi.thread;
  2.  
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;
  5.  
  6. public class LockSample {
  7.   private int count;
  8.   private final Lock lock = new ReentrantLock();
  9.  
  10.   public static void main(String[] args) {
  11.     var ls = new LockSample();
  12.     ls.execute();
  13.   }
  14.  
  15.   public void execute() {
  16.     final int THREAD_MAX = 300000;
  17.     var ts = new Thread[THREAD_MAX];
  18.     for (var i = 0; i < THREAD_MAX; i++) {
  19.       ts[i] = new Thread(new MyThread(this));
  20.       ts[i].start();
  21.     }
  22.     for (var i = 0; i < THREAD_MAX; i++) {
  23.       try {
  24.         ts[i].join();
  25.       } catch (InterruptedException e) {
  26.         System.out.println(e);
  27.       }
  28.     }
  29.     System.out.println(count);
  30.   }
  31.  
  32.   public void increment() {
  33.     lock.lock();
  34.     try {
  35.       this.count++;
  36.     } finally {
  37.       lock.unlock();
  38.     }
  39.   }
  40.  
  41.   private static class MyThread implements Runnable {
  42.     private LockSample _counter;
  43.  
  44.     public MyThread(LockSample counter) {
  45.       this._counter = counter;
  46.     }
  47.  
  48.     @Override
  49.     public void run() {
  50.       _counter.increment();
  51.     }
  52.   }
  53. }

ReentrantLockクラスでlockメソッドを利用した場合には、その直後からtryブロックで括るのを忘れないようにしてください。これは処理中に思わぬ例外が発生した場合にも、finally句でunlockメソッドが呼び出されることを保証するためです。

関連ページ

スレッド_目次
Threadクラス/Runnableインターフェイス
synchronized修飾子/ブロック
ReentrantLockクラス
AtomicXxxxxクラス
Executorsクラス

監修

山田祥寛(有限会社 WINGSプロジェクト)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NEC にてシステム企画業務に携わるが、2003年 4 月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト(https://wings.msn.to/)」の代表でもある。主な著書に『改訂 3 版JavaScript 本格入門』(技術評論社)、「独習シリーズ(C#・Python・PHP・Ruby・JSP&サーブレットなど)」(翔泳社)、「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravel など)」(Amazon Kindle)など。売り上げの累計は100万部を超える。