質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

スレッドセーフ

マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

Q&A

解決済

3回答

5699閲覧

マルチスレッド、スレッドセーフがいまいちわからない

lupus_dingo

総合スコア257

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

スレッドセーフ

マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

0グッド

6クリップ

投稿2017/11/12 09:47

編集2017/11/12 09:50

今まで避けてきたワードなのですが、
そうも行かなくなりそうなので質問させてください。

シングルスレッド、マルチスレッド、スレッドローカル、シングルトン、プロトタイプなどのキーワードで検索してみたのですがいまいち理解できません。

以下の認識で合っているか教えて下さい。
前提はspringframeworkを使用したWebアプリです。

・シングルトン
システムで1インスタンスを使い回す。
つまり、アプリが起動して最初にインスタンス生成されたものをずっと使い回す。当たり前だがリクエストごとの状態を持たせてはいけない。

・シングルスレッド
一つのスレッドで全ての処理が行われる実行環境。
一つのインスタンスに同時にアクセスされることがないため安全だが効率が悪い。
(リクエストの概念がないバッチアプリは一回実行されるだけなのでシングルスレッド?)

・マルチスレッド
複数のリクエストを同時に処理する実行環境。
現在のJavaプログラムはこれ?
スレッドローカルでないクラス変数は全て同時にアクセスされる可能性があるので、リクエストごとの状態を持つインスタンスはクラス変数にしてはいけない(必ずメソッド内で定義&インスタンス生成)。

・スレッドローカル
threadLocalを使用して作成したクラス変数のこと。
シングルトンならシステムで1インスタンスだが、スレッドローカルはスレッド(≒リクエスト?)ごとに1インスタンスだから、例えば、
多くのメソッドで必要になる変数だがメソッドの引数に毎回同じ指定なんてしたくない場合に便利。

・スレッドセーフ
マルチスレッド環境でも同時に処理されることがないクラス変数。以下のようにしてsynchronizedで囲むだけ。排他がかかるのでパフォーマンスは落ちる。

synchronized(変数){
//指定した変数に対して行う処理。
//この中に書いた処理は全て終了するまで排他制御がかかる。
}

これらについて認識合っているか教えて欲しいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

おおざっぱな理解のための例え話をしようと思います。


例えば管理者(あなた)と作業者Aさんが居たとします。Aさんは、あなたから渡される指示書に書かれたことを行います。

あなたはAさんに三枚の指示書を渡しました。Aさんは渡された指示書を、渡された順にこなしていきます。これがシングルスレッドです。作業者が一人しかおらず、作業も渡された順に一つずつこなす状態です。

ここに作業者Bさんが合流しました。BさんもAさんと同じように渡された指示書に書かれたことを行う人です。

今度はAさん、Bさんに同時に別々の指示書を渡しました。AさんBさんはそれぞれ自分に渡された指示書をこなします。これがマルチスレッドです。作業者が二人以上おり、同時並行で作業が進みます。

Aさん、Bさんは作業の進行を円滑に行うために、それぞれ自分用のメモ帳を持っています。これがスレッドローカルです。Aさんのメモ帳はAさんしか見ませんし、Bさんのメモ帳はBさんしか見ません。

あなたは机の上に大きな模造紙を一枚だけ用意しました。この模造紙にある計算結果をどんどん書いてもらうことが目的です。一枚しか用意しないので、作業者は間違えようがありません。これがシングルトンです。全作業者が共通で持つ、全体で1つしかないことが保証されたものです。

AさんBさんにそれぞれ「こういった計算をして、この模造紙にどんどん書いていってほしい」という指示書を出しました。AさんBさんはそれぞれ自分の手元のメモ帳を使って計算し、計算が終わり次第模造紙に書くことにしました。

しかしここで問題が起きます。AさんとBさん、交互に模造紙に書けばいいものを、同時に模造紙に書き始めてしまいました。Aさんが書いた文字、Bさんが書いた文字が入り乱れてわけがわからないものが出来上がります。これではまずいということで、模造紙に書くときは「作業中です」という札を立てて、お互いが干渉しないルールを作りました。これがスレッドセーフです。

まとめ

  • シングルスレッドは作業者が一人しかおらず、渡された処理を渡された順にこなしていく
  • マルチスレッドは作業者が二人以上おり、それぞれの作業が同時に進む
  • 作業者ごとにスレッドローカルと呼ばれるメモ帳のようなものを持っている
  • 全作業者がアクセス可能で、全体に一つしかないものがシングルトン
  • スレッドセーフにしないとお互いが影響しあってまずいことになる

投稿2017/11/13 01:43

編集2017/11/13 02:01
masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masaya_ohashi

2017/11/13 02:01

シングルトンの説明が抜けていたので追記しました。
guest

0

私もそんなにマルチスレッドに関しては詳しいわけではないのですが1点だけ。

・スレッドセーフ

マルチスレッド環境でも同時に処理されることがないクラス変数。以下のようにしてsynchronizedで囲むだけ。排他がかかるのでパフォーマンスは落ちる。

synchronized(変数){

//指定した変数に対して行う処理。
//この中に書いた処理は全て終了するまで排他制御がかかる。
}

synchronizedしているものだけがスレッドセーフというわけではありません。マルチスレッドで同時処理する場合に問題が起こるのは、Chironianさんも説明されていますが、各スレッドのタイミングの問題で変数の変化が想定通りの回数起こらない場合などです。変化しないものであれば、つまり読み取り専用であればどのスレッドからどのタイミングで参照されても値は同じなのでスレッドセーフということになります。

投稿2017/11/12 12:37

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/11/12 22:18

>変化しないものであれば、つまり読み取り専用であればどのスレッドからどのタイミングで参照されても値は同じなのでスレッドセーフということになります。 確かにそうでした。 回答ありがとうございます。
guest

0

こんにちは。

まず、「スレッド」の概念は理解されていますでしょうか?

プログラムを実行する「主体」みたいなものですね。それをスレッドと呼びます。プロセスが起動されたら、そのエントリーポイント(CやC++はmain()関数です。Javaはmain()メソッド?)からスレッドが実行を開始します。
この時点ではシングル・スレッドです。そのまま、サブスレッドを起動しなかった場合はシングル・スレッドのまま動作を継続します。最後にmain()からリターンするなどによりプログラムを終了します。

サブスレッドを起動するとマルチ・スレッド・プログラムとなります。同じプロセス内で起動されたスレッドは、同じプロセス内にあるメモリにアクセスできます。

今、ある変数xがあり、2つのスレッドaとbが変数xをインクリメントすると仮定します。
インクリメントする場合、そのメモリの内容を読み出して1加えて元のメモリへ書き込みます。これをRead-Modify-Writeといいます。

非常に運が悪く、2つのスレッドが変数xを同時にインクリメントしたとします。x==0の時に2つのスレッドがインクリメントした場合でも、期待する結果はx==2となることですね。

さて、同時と言っても同じメモリを全く同時にアクセスすることはできないよう、コンピュータのハードウェアが調整します。その結果、下記の順序でアクセスしたと仮定します。

  1. スレッドaがread
  2. スレッドbがread
  3. スレッドaが読み出した値をインクリメント(1になる)
  4. スレッドbが読み出した値をインクリメント(1になる)
  5. スレッドaがwrite(xが1になる)
  6. スレッドbがwrite(xは1のまま)

ということで、残念ながら期待通りの動作になりません。

これがマルチ・スレッドの危険性です。もちろんインクリメントに限りません。他にも様々なパターンのリスクが存在しています。

このリスクを回避する仕組みを備えている機能は「スレッドセーフ」と呼ばれます。
また、スタック上のメモリとスレッド・ローカル・ストレージ上のメモリはそれを所有しているスレッドだけがアクセスできますので、安心してアクセスできます。逆にそれ以外のメモリは全てリスクを抱えています。
複数のスレッドが同時にアクセスすることがないよう、複数のスレッドで共有しないようにしたり、共有する場合はミューテックスで排他制御したりします。

因みに、シングルトンやスレッド・ローカル・ストレージは一種のグローバル変数ですから、使わないで済む場合はなるべく使わない方が良いです。(必要な時は当然使うべきですが)これはシングル・スレッド・プログラムの場合となんら変わりません。

投稿2017/11/12 10:45

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/11/12 22:24

丁寧な回答ありがとうございます。 >この時点ではシングル・スレッドです。そのまま、サブスレッドを起動しなかった場合はシングル・スレッドのまま動作を継続します。 サブスレッドを起動するかしないかは何によって変わるのでしょうか? >同じプロセス内で起動されたスレッドは、同じプロセス内にあるメモリにアクセスできます。 なるほど勉強になります。 >因みに、シングルトンやスレッド・ローカル・ストレージは一種のグローバル変数ですから、使わないで済む場合はなるべく使わない方が良いです。 スレッド・ローカル・ストレージとはなんでしょうか?
Chironian

2017/11/13 05:13

> サブスレッドを起動するかしないかは何によって変わるのでしょうか? Javaの詳しいことは把握していませんが、↓などの方法で起動します。 http://www.itsenka.com/contents/development/java/topics/thread2.html これらのような何らかの方法で起動しているかどうかです。 使っているライブラリやフレームワークが(こっそり)起動していることもあります。 > スレッド・ローカル・ストレージ スレッド毎に設けられたstatic変数です。Javaでは、本当にstaticなのかどうかよく把握していませんが、いくつかあるサンプルを見る限りでは皆さんstaticメンバ変数に設定しています。 staticメンバ変数はちょっと油断(publicにしたりアクセサを設けたり)すると直ぐに事実上のグローバル変数になりますから要注意なのです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問