Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Java

Javaのsynchronizedとは?ある場合とない場合のサンプルPGを比較付き

投稿日:2021年6月21日 更新日:

<目次>

(1) Javaのsynchronizedとは?ある場合とない場合のサンプルPGを比較付き
 (1-1) synchronizedの概要
 (1-2) synchronizedの構文
 (1-3) synchronizedが無い場合(非同期)の例
  ●main文(スレッド生成・実行)
  ●各スレッドの中で実行する処理
  ●同期対象のオブジェクト
 (1-4) synchronizedがある場合(同期)の例①【メソッドをsynchronized】
 (1-5) synchronizedがある場合(同期)の例②【オブジェクトをsynchronized】

(1) Javaのsynchronizedとは?ある場合とない場合のサンプルPGを比較付き

(1-1) synchronizedの概要

マルチスレッドの処理において、複数スレッドが同時に同じ共有データを更新しようとした場合に「競合状態」が発生する可能性があります。Javaではそれを防ぐための「同期」機能(synchronizedキーワード)があります。

synchronizedを使ったブロックは、データに同時にアクセスする「スレッド」を1つに限定する事ができ、これにより「競合状態」を防ぐ事ができます。

目次にもどる

(1-2) synchronizedの構文

「synchronized」キーワードの( )の中に同期対象のリソース、つまりロックを掛けて1スレッドのみが使える対象のオブジェクト(変数でもオブジェクトでも)を指定します。{  }の中で、オブジェクトのロックを取得した際に実行する処理を指定します。

(構文)
synchronized([同期対象のリソース])
{
   //# 共有アクセスにリソースして処理を行う
}

これにより、synchronizedの箇所に到達すると、スレッドが対象リソース(オブジェクトや変数など)を自動でロックし、他のスレッドがアクセスできないように制御します。そしてスレッドの処理が完了すると、ロックを解放します。

目次にもどる

(1-3) synchronizedが無い場合(非同期)の例

「同期」(synchronized)のサンプルプログラムを見る前に、「synchronized」を使わない場合(非同期)に起きる弊害の例をご紹介します。

●main文(スレッド生成・実行)

スレッド1(st1)とスレッド2(st2)を生成・処理実行するmain文です。SyncCalc型の「scobj」は同期対象のオブジェクト(1度に1スレッドのみロックを許可する)対象です。

//# 【クラス】2つのスレッドで処理を流すmain文
//# (synchronized確認用)
public class SynchronizedSample {
    //# main文
    public static void main(String args[]) {

        //# 同期対象のリソース
        //#(1度に1スレッドのみ専有可能)
        SyncCalc scobj = new SyncCalc();

        //# 各スレッドのインスタンス生成
        SyncTask st1 = new SyncTask(scobj, 2);
        SyncTask st2 = new SyncTask(scobj, 3);
        //# 各スレッドの処理実行
        st1.start();
        st2.start();
    }

}

 

目次にもどる

●各スレッドの中で実行する処理

各スレッドにて、累乗計算を起動するスレッド(Threadを継承)のクラスです。

//# 【クラス】各スレッドの中で実行する処理
public class SyncTask extends Thread {

    //# メンバ変数
    private SyncCalc sc;
    private int calctarget;

    //# コンストラクタ
    SyncTask(SyncCalc sc,int calctarget){
        this.sc = sc;
        this.calctarget = calctarget;
    }

    //# スレッドに必要なrunメソッドのオーバーライド
    public void run() {
        //# 累乗の計算を実行
        sc.calculate(calctarget);
    }
}

目次にもどる

●同期対象のオブジェクト

ロック対象の「SyncCalc」クラスです(ただの累乗計算)。

//# 【クラス】同期対象のオブジェクト(各スレッドのロック対象)
public class SyncCalc {
  void calculate(int num) {
    //引数の1乗~5乗を計算
    for(int i=1; i<=5; i++) {
      System.out.println(num+" の "+i
          +" 乗 = "+(int)Math.pow(num,i));
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}
 
(図131)実行結果
スレッド1(st1)とスレッド2(st2)の計算結果が入り混じってしまっています。
 

目次にもどる

(1-4) synchronizedがある場合(同期)の例①【メソッドをsynchronized】

次に上記の非同期のサンプルに「synchronized」キーワードを追加して同期処理にした例①をご紹介します。この例では「メソッド」に対してsynchronizedを付与する事で同期しています。

変更箇所は1カ所だけで、同期対象のオブジェクト「SyncCalc」クラスのメソッドに「synchronized」キーワードを追加した以外は全て一緒です。
(変更前)
 
//# 【クラス】同期対象のオブジェクト(各スレッドのロック対象)
public class SyncCalc {
  void calculate(int num) {

 

(変更後)

//# 【クラス】同期対象のオブジェクト(各スレッドのロック対象)
public class SyncCalc {
  synchronized void calculate(int num) {
 
(図141)

目次にもどる

(1-5) synchronizedがある場合(同期)の例②【オブジェクトをsynchronized】

次に上記の非同期のサンプルに「synchronized」キーワードを追加して同期処理にした例②をご紹介します。この例では「オブジェクト」に対してsynchronizedを付与する事で同期しています。

こちらも変更箇所は1カ所だけで、スレッドのrunクラス内で使用している「SyncCalc」のインスタンスに「synchronized」キーワードを追加した以外は全て一緒です。
(変更前)

    //# スレッドに必要なrunメソッドのオーバーライド
    public void run() {
        //# 累乗の計算を実行
        sc.calculate(calctarget);
    }

 

(変更後)

    //# スレッドに必要なrunメソッドのオーバーライド
    public void run() {
        //# 累乗の計算を実行
        synchronized(sc){
            sc.calculate(calctarget);
        }
    }

 

(図142)

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Java

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

Javaのprintfで日付の書式設定を行う方法

<目次> (1) Javaのprintfで日付の書式設定を行う方法  (1-1) printfの基本構文  (1-2) 時刻に関するフォーマット  (1-3) 日付に関するフォーマット (1) Jav …

Newton法で平方根を求めるJavaのサンプルプログラム+操作動画もご紹介

<目次> (1) Newton法で平方根を求めるJavaのサンプルプログラム  (1-1) Newton法の式を簡単に復習  (1-2) Newton法のサンプルプログラム (1) Newton法で平 …

Javaで実装したLinkedListのサンプルプログラムをご紹介

<目次> (1) Javaで実装したLinkedListのサンプルプログラムをご紹介  (1-1) LinkedListの概要  (1-2) LinkedListの特徴  (1-3) LinkedLi …

JavaのDequeの概要や使い方+サンプルプログラムもご紹介

<目次> (1) JavaのDequeの概要や使い方+サンプルプログラムもご紹介  (1-1) Dequeとは?  (1-2) Dequeを実装したクラス  (1-3) Dequeの使い方  (1-4 …

Javaのprintfで右揃え(右詰め)や左揃え(左詰め)にフォーマットする方法

<目次> (1) Javaのprintfで右揃えや左揃えにフォーマットする方法  (1-1) 構文  (1-2) 右揃えの方法  (1-3) 左揃えの方法  (1-4) 主要な変換文字(s,d,f,t …

  • English (United States)
  • 日本語
Top