Rainbow Engine

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

C#

C#のlockとは?意味や使い方とサンプルプログラムをご紹介

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

 

<目次>

(1) C#のlockとは?意味や使い方とサンプルプログラムをご紹介
 (1-1) 概要
 (1-2) 構文
 (1-3) サンプルプログラム
 (1-4) lockステートメントを使わないと・・

(1) C#のlockとは?意味や使い方とサンプルプログラムをご紹介

(1-1) 構文

lockステートメントはオブジェクトに対する相互排他(mutual exclusion)を行います。「相互排他」は、複数のプロセスで共有する資源で競合(同時アクセス)が発生した場合に、あるプロセスにて資源をロックして他プロセスが使用できないように排他する事で、データの整合性を保つ仕組みの事をいいます。

Javaでいう所の「synchronized」と同じようなものです。
 

(1-2) 構文

lockステートメントで指定したリソース(オブジェクト)に対して相互排他ロックを取得し、ブロック内({ }内)の処理を実行し、処理完了後にロックを解放します。

(構文)

lock ([ロック対象のオブジェクト])
{
	//# ロック取得後の処理
}

 

目次にもどる

(1-3) サンプルプログラム

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

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestProject
{
  class LockStatementTest
  {
    static void Main(string[] args)
    {
      //# ロック対象のオブジェクト
      LockCalc lc = new LockCalc();

      //# 各スレッドのインスタンス生成
      LockTask task1 = new LockTask(lc, 2);
      LockTask task2 = new LockTask(lc, 3);

      Thread thr1 = new Thread(new ThreadStart(task1.runCalc));
      Thread thr2 = new Thread(new ThreadStart(task2.runCalc));
      thr1.Start();
      thr2.Start();
    }
  }
}

 

目次にもどる

●クラス①:各スレッドの中で実行する処理のオブジェクト

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestProject
{
  class LockTask
  {
    //# フィールド
    private LockCalc lc;
    private int calcTarget;

    //# コンストラクタ
    public LockTask(LockCalc lc, int calcTarget)
    {
      this.lc = lc;
      this.calcTarget = calcTarget;
    }

    //# 計算メソッドの呼び出し
    public void runCalc()
    {
      //# ■オブジェクトをロック
      lock (lc)
      {
        lc.calculate(calcTarget);
      }
    }
  }
}

 

目次にもどる

●クラス②:同期対象のオブジェクト

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace TestProject
{
  class LockCalc
  {
    //# 計算メソッドの呼び出し
    public void calculate(int num)
    {
      for (int i = 1; i <= 5; i++)
      {
        Console.WriteLine("{0} の {1} 乗 = {2}", num, i, (int)Math.Pow(num, i));
        Thread.Sleep(100);
      }
    }
  }
}
 
実行結果は、まず1つ目のスレッド(thr1)の繰り返し計算が一通り行われて完了した後に、2つ目のスレッド(thr2)の計算が行われています。これはlockにより「LockCalc」クラスのオブジェクトをロックした結果です。

 

(図151)実行結果

目次にもどる

(1-4) lockステートメントを使わないと・・

次に上記のサンプルで「lock」ステートメントを指定せずに非同期処理にした例②をご紹介します。この例では「LockCalc」をlockしていないため、1つ目のスレッド(thr1)と2つ目のスレッド(thr2)の計算が交互に入り混じって出力されてしまっています。

変更箇所は1カ所だけで、スレッド処理(TestProject)のクラス内で使用している「LockCalc」のインスタンス「lc」に対して「lock」ステートメントを追加した以外は全て一緒です。
 
(lockなし版)
//# 計算メソッドの呼び出し
public void runCalc()
{
    lc.calculate(calcTarget);
}
 
(lockあり版)

//# 計算メソッドの呼び出し
public void runCalc()
{
    lock (lc)
    {
        lc.calculate(calcTarget);
    }
}

 

(図141)実行結果

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-C#

執筆者:


comment

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

関連記事

C#で文字列をタブやスペースで区切り配列に格納する方法

<目次> (1) C#で文字列をタブやスペースで区切り配列に格納する方法  (1-1) 基本構文  (1-2) 基本構文サンプルプログラム  (1-3) 応用構文  (1-4) 応用構文サンプルプログ …

C#で見るgetやsetとは?プロパティの基礎についてご紹介

<目次> (1) C#で見るgetやsetとは?プロパティの基礎についてご紹介  (1-1) プロパティとは?  (1-2) プロパティの構文  (1-3) サンプルプログラム  (1-4) プロパテ …

ASP.NET MVCのRouteConfigを追加する方法を2つご紹介

  <目次> (1) ASP.NET MVCのRouteConfigを追加する方法を2つご紹介  (1-1) やりたい事の整理  (1-2) 方法1:通常のルーティング  (1-3) 方法2 …

ASP.NETでViewに値を渡す方法

  <目次> (1) ASP.NETでViewに値を渡す方法  (1-1) 方法1:アクションメソッドの引数に追加  (1-2) 方法2:ViewBagを使う方法  (1-3) 方法3:ビュ …

C#のコンソールアプリで引数を与えて実行する方法

<目次> (1) C#のコンソールアプリで引数を与えて実行する方法  (1-1) 設定箇所  (1-2) サンプルプログラム  (1-3) サンプルプログラムの補足 (1) C#のコンソールアプリで引 …

  • English (United States)
  • 日本語
Top