Javaのスレッドについて 2005年7月6日 海谷 治彦.

Slides:



Advertisements
Similar presentations
アルゴリズムとプログラミン グ (Algorithms and Programming) 第6回:クラスとインスタンス クラスの宣言 アクセス修飾子 インスタンスの生成 (new キーワード) this キーワード フィールドとメソッドの実際の定義と使い 方 クラスの宣言 アクセス修飾子 インスタンスの生成.
Advertisements

独習JAVA Chapter 6 6.6 クラスの修飾子 6.7 変数の修飾子 結城 隆. 6.6 クラスの修飾 abstract インスタンス化できないクラス。1つまたは複数のサブクラスで 実装してはじめてインスタンス化できる。 final 継承されたくないことを明示する。これ以上機能拡張 / 変更でき.
6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
社会人学習講座 「Javaプログラミング概論」
マルチスレッド処理 (II) Multithreading
第2回 プロセス管理 ジョブ、プロセスとは? プロセスの状態遷移 プロセス制御ブロック スケジューリング.
コンパイラ 2011年11月14日
アルゴリズムとデータ構造 2012年6月27日
スレッドの同期と、スレッドの使用例 スレッドの同期 Lockオブジェクト: lockオブジェクトの生成
アルゴリズムとデータ構造1 2007年6月12日
アルゴリズムとプログラミング (Algorithms and Programming)
実行時のメモリ構造(1) Jasminの基礎とフレーム内動作
Javaのインタフェース についての補足 2006年5月17日 海谷 治彦.
オペレーティングシステムJ/K 2004年10月7日
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
計算機プログラミングI 第12回 2003年1月23日(木) インターフェース スレッド 最後に お知らせ クイズ 授業アンケート
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
第20章 Flyweight ~同じものを共有して無駄をなくす~
インタフェース プログラミング 第14回 インタフェース プログラミング第14回.
オブジェクト指向入門.
計算機プログラミングI 第8回 2002年12月5日(木) メソッドとクラス (教科書6章) クイズ インスタンスメソッド インスタンス変数
CONCURRENT PROGRAMMING
第9回 プロセスの協調と排他制御 並行プロセスと資源の競合 競合問題 セマフォ 不可分命令の実装 プロセス間通信 PV命令
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
進捗 Javaバイトコード変換による 細粒度CPU資源管理
~手続き指向からオブジェクト指向へ[Ⅱ]~
実行時のメモリ構造(2) Javaスタック内動作他
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
8.1 例外処理 8.2 catchブロックの検索 8.3 throwステートメント 8.4 例外とエラークラス 8.6 独自の例外
アルゴリズムとプログラミング (Algorithms and Programming)
細かい粒度で コードの再利用を可能とする メソッド内メソッドと その効率の良い実装方法の提案
独習Java ・ 8.1  例外処理 ・ 8.2  catch ブロックの検索  12月 5日    小笠原 一恵.
第9章 例外処理,パッケージ 9.1 例外処理 9.2 ガーベッジコレクション.
オブジェクト指向 プログラミング 第八回 知能情報学部 新田直也.
独習JAVA 6.8 コンストラクタの修飾子 6.9 メソッドの修飾子 6.10 ObjectクラスとClassクラス 11月28日(金)
オブジェクト指向 プログラミング 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
リファレンスの復習と例外処理 2005年6月14日 海谷 治彦.
C言語でスレッド (Pthread) 2007年1月11日 海谷 治彦.
第6回 2007年6月1日 応用Java (Java/XML).
アルゴリズムとプログラミング (Algorithms and Programming)
暗号技術 ~JAVAプログラム①~ (5週目)
Collection, Generics, Iterator
11 ソフトウェア工学 Software Engineering デザインパターン DESIGN PATTERNS.
クラスファイルの構造解析(2) 2003年6月23日 海谷 治彦.
7.4 intanceof 演算子 7.5~7.9パッケージ 2003/11/28 紺野憲一
東京工業大学 情報理工学研究科 数理・計算科学専攻 千葉研究室 栗田 亮
プログラミング基礎a 第12回 Java言語による図形処理入門(3) アニメーション入門
プログラミング基礎a 第11回 Java言語による図形処理入門(3) アニメーション入門
パッケージ,アクセス修飾子 2008年4月27日 海谷 治彦.
アルゴリズムとデータ構造 2011年6月23日
オブジェクト プログラミング 第2回 プログラムの基本.
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
同期処理のモジュール化を 可能にする アスペクト指向言語
計算機プログラミングI 木曜日 1時限・5時限 担当: 増原英彦 第1回 2002年10月10日(木)
アルゴリズムとプログラミング (Algorithms and Programming)
計算機プログラミングI 第4回 2002年10月31日(木) 問題解決とアルゴリズム クラスメソッドと手続きの抽象化 最大公約数
オペレーティングシステムJ/K (並行プロセスと並行プログラミング)
プログラミング基礎a 第9回 Java言語による図形処理入門(1) Javaアプレット入門
アルゴリズムとデータ構造 2012年6月25日
プログラミング実習(Java) グラフィクス処理とGUIプログラミング 講師:坂口 利裕(横浜市立大学)
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
ねらい 数値積分を例題に、擬似コードのアルゴリズムをプログラムにする。
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
プログラミング 2 静的変数.
Presentation transcript:

Javaのスレッドについて 2005年7月6日 海谷 治彦

並列動作 複数の処理が同時に動くこと. 自然界?ではあたりまえ. ハードウェアを伴う機器制御でもあたりまえ.

例: テレビの制御 音量を変更 放送を表示 音量変更中に,放映(画,音)が停止したら,やっぱ怒るよねぇ.

並列と並行 (用語の話) 並列 (parallel) 並行 (concurrent) 複数の仕事を同時に行う. 並行 (concurrent) 潜在的に同時進行可能な処理を論理的に表現したプログラムの性質. よって,Javaでは並行処理を記述できるが,それが並列に実行されるかはマシン次第.

プロセス VS スレッド プロセス (もしくはタスク) スレッド OSレベルで,独立した処理単位 ファイル等は共有できるが変数等は共有できない. 詳細はOSの授業にて. スレッド 1つのプログラム内での異なる処理の流れ. 1つのプログラム内なので,当然,変数等も共有できる.

複数動くプロセスの観察(linux) psコマンドでプロセスを表示できる.

いままでやってきたプログラム 所謂 フローチャート main(){ int a, b, i; ..... if(a>b){ a++; }else{ ........ } for(i=... ){ いままで学んできたプログラムは,ある一瞬には,ある1つの命令しか実行されていなかった. 処理の流れは一本である. yes no a>b a++ ...... i= ... no .... yes ......

スレッドを利用したプログラム 独立並行して動く. 変数も共有できる. class MyThread extends Thread{ static int a=0; ... run(){ for(int i....){ a++; } .... main(....){ ..... new MyThread().start(); .... i= ... .... a++ yes no i= ... .... a++ yes no i= ... .... a++ yes no 独立並行して動く. 変数も共有できる.

典型的なThreadの作り方 Threadというクラスのサブクラスを作る. public void run() メソッドを実装する. この中が実際並行に動作する処理となる. Threadサブクラスのインスタンスを作り,そのインスタンスにstart()メソッドを適用する. run()メソッドが,start()メソッドからOSに指示に従い,呼び出される. run()メソッドは通常,ユーザープログラムでは呼ばない.

スレッドのライフサイクル (状態遷移図) th=new MyThread() 存在しているだけ th.start() 実行状態 実行待ち状態 run()内部の実行 実行待ち状態 ここの遷移はOSが適当に決める 終了

スレッドのスケジュール (1CPUの場合) マシン 利用可能時間 スレッド1のrun() スレッド2のrun() スレッド3のrun()

例: IDの並行表示 実際のところ,全然ばらばらに表示されない. スケジュールに対して,run()の内容があまりに短いから. public class NumOut extends Thread{ private int id; NumOut(int id){ this.id=id; } public void run(){ for(int i=0; i<10; i++){ System.out.print(id+" "); } public static void main(String[] args){ new NumOut(1).start(); new NumOut(2).start(); new NumOut(3).start(); 実際のところ,全然ばらばらに表示されない. スケジュールに対して,run()の内容があまりに短いから. 個々の処理に明示的に「休止」処理を入れれば並行っぽく見える. (Webページの方参照)

並行処理が並列っぽく見えない? public class NumOut extends Thread{ private int id; private static int max=30; private static int tnum=4; NumOut(int id){ this.id=id; } public void run(){ for(int i=0; i<max; i++){ System.out.print(id+" "); } public static void main(String[] args){ Thread.currentThread().setPriority(Thread.MAX_PRIORITY); for(int i=0; i<tnum; i++) new NumOut(i+1).start();

理由 1CPUのマシンでやってるので当たり前. それにしても,もちっとバラバラになってほしい. それぞれのスレッドの処理が小さいので,スタートした順に処理が終わってしまう(涙)

明示的な実行権の委譲 yeild スレッドには, public static void yeild() が定義されている. このメソッドを呼ぶと,実行可能な他のスレッドに明示的に実行権を譲ることができる. なんとなく,linux2.2ではうまく yieldが動作しない? (裏はとってませんが)

Yieldの効果 少しは,「並列に」動いているっぽくみえるようになった. public class NumOutYield extends Thread{ private int id; private static int max=30; private static int tnum=4; NumOutYield(int id){ this.id=id; } public void run(){ for(int i=0; i<max; i++){ System.out.print(id+" "); yield(); } public static void main(String[] args){ Thread.currentThread().setPriority(Thread.MAX_PRIORITY); for(int i=0; i<tnum; i++) new NumOutYield(i+1).start(); 4年のOSでは,うまく「並列に」動いているっぽく実行できなかった.Linuxカーネルのせい?

休止処理 sleep sleep(long x): Threadクラスに定義されており,そのスレッドをxミリ秒停止させる. 例えば,ランダムに停止時間を与えたい場合,以下のようなクラスを利用するなど. import java.util.*; class Waiting{ private Random r; Waiting(){ r=new Random();} void wait(Thread t){ int w=r.nextInt(); w=(w>0? w: w*(-1))%500; try{ t.sleep(w);}catch(InterruptedException e){} }

sleepをつかいバラバラに見せる import java.util.*; public class NumOutSleep extends Thread{ // 中略 private Random r=new Random(); public void run(){ for(int i=0; i<max; i++){ System.out.print(id+" "); try{Thread.currentThread().sleep(r.nextInt(2));} catch(Exception e){} }

並行処理の大切なこと 安全性(safety): 好ましくない状態にならない 干渉(interfere)がおきない. デッドロック(dead lock)が無い. 生存性(liveness): やろうとしたことはいづれ処理される.(永遠に待たされることは無い)

干渉とデットロック 干渉(interfere) 並行処理のミスでデータ等の一貫性が失われること. デッドロック(dead lock) 後述の排他制御である程度回避可能. デッドロック(dead lock) 複数の資源を同時に必要とする複数のプロセス(スレッド)が,資源の一部をそれぞれに確保し,残りの資源が空くまで,それぞれが永久に待ってしまうこと. 「哲学者の例題」参照.

排他制御による干渉の予防 (スレッドだけでなく)並行処理一般に重視しなければいけない問題. 要は共有資源を同時に処理しちゃいけない. 一般にはロックという方法で排他制御するのが一般的.

有名な干渉の例 長野店 口座DB 池袋店 100万円 時間の流れ 150万円 90万円 ???? 100+50-10=140 じゃないの? 10万 出金 100万 50万 入金 時間の流れ 150万 150万円 90万 90万円 ???? 100+50-10=140 じゃないの?

干渉発生のTIPS 1つの連続した処理が終わる前に,古いデータを読んで,別処理を行っているのがマズい. 逐次処理(not並行処理)の場合は問題なし. スレッドによる並行処理の場合,データ(変数,ファイル,レコード等)を特定のスレッドに一定期間のみ占有させる必要あり.

Javaにおける排他制御 Synchronizedブロック Synchronized メソッド インスタンスをもとにした,処理ブロックのロック. Synchronized メソッド メソッド毎のロック

synchronized ブロックの例 Inc extends Thread get Counter set +1 private int c get Inc extends Thread int get() 値をcを返す set +1 void set(int) 値をcにセット cを表示 get Inc extends Thread set +1

干渉が起きる理由 class Inc extends Thread{ // 中略 public void run(){ for(int i=0; i<often; i++){ int tmp=c.get(); tmp++; try{ sleep(r.nextInt(2));}catch(Exception e){} c.set(tmp); } 詳細はHPを参照

干渉の抑制 public void run(){ for(int i=0; i<often; i++){ synchronized(c){ int tmp=c.get(); tmp++; try{ sleep(r.nextInt(2));} catch(Exception e){} c.set(tmp); } この処理の間は, インスタンス c は この処理を行うスレッド に占有される.

synchronized メソッドの例 Inc extends Thread inc Counter private int c inc int inc() 値をcを 1つ増やす. 値を表示 inc Inc extends Thread

干渉が起きる理由 class Counter{ private int c; private Random r=new Random(); public void inc(){ int tmp=c; tmp++; try{Thread.currentThread().sleep(r.nextInt(2));} catch(Exception e){} c=tmp; System.out.print(c+" "); }

干渉の抑制 このメソッドが呼ばれた インスタンスは, メソッドの処理が終わるまで, メソッドを呼んだスレッドに占有される. class Counter{ private int c; private Random r=new Random(); synchronized public void inc(){ int tmp=c; tmp++; try{Thread.currentThread().sleep(r.nextInt(2));} catch(Exception e){} c=tmp; System.out.print(c+" "); }

デッドロックについて HPにある「大工」の問題を参照 「哲学者」の問題の変型版.

共有資源と待ち行列 Javaのロックメカニズムでは, ロックされる共有資源(インスタンス)と, それの利用を待っているスレッドの スレッドの待ち行列 Javaのロックメカニズムでは, ロックされる共有資源(インスタンス)と, それの利用を待っているスレッドの 待ち行列が存在する. 共有資源 (インスタンス)

行列から一時外れる スレッドの待ち行列 インスタンスがある条件を満たしていないと,処理を行えないスレッド(A)があるとして,その条件は他のスレッド(B)が満たせるとしたら,Aは順番を譲って,他のスレッドが処理を終えるのを待たねばならない. 共有資源 (インスタンス)

例 スレッドの待ち行列 共有資源 (インスタンス) タバコ業者でーす. (マイルドセブン補給できます) マイルドセブン 品切れ マイルドセブンがほしい. 共有資源 (インスタンス)

wait, notify, notifyAll あるインスタンスをロック中のスレッドが呼び出せるメソッド. Objectクラスで定義されている. ⇒ 全てのJavaクラスで定義されている. wait() これを呼び出したスレッドを待機状態にする. notify() 待機中のスレッドを1つ再開させる. notifyAll() 待機中のスレッドを全て再開させる.

例 スレッドの待ち行列 共有資源 (インスタンス) タバコ業者でーす. (マイルドセブン補給できます) 補給がすんだら,notify等を呼んで, 待機中のスレッドを列にもどす. マイルドセブン品切れ 業者が補給すれば, 品切れは解除される. マイルドセブンがほしい. wait() を呼んで待機. ⇒ 一時,列から離れる. 共有資源 (インスタンス)

プログラムの例 所謂,生産者・消費者問題 生産過剰気味の構成にしてあるので,すぐにストック上限(本プログラムでは30に固定)あたりをうろうろする. しかし,止まりはしない.

コード (Stock.java) class Stock extends IntLabel{ private static final int max=30; // 中略 // ストックから販売する synchronized void buy(){ while(empty()){ try{ wait(); } catch(Exception e){} } super.dec(); notifyAll(); // ストックに補給する synchronized void supply(){ while(full()){ try{ wait(); } catch(Exception e){} } super.inc(); notifyAll();

コード (Customer, Producer) class Customer extends LabelUpdater{ Customer(IntLabel l, Stock s){ super(l,s); } public void run(){ while(true){ stock().buy(); inc(); // 買った個数を記録 sleeping(1000); class Producer extends LabelUpdater{ Producer(IntLabel l, Stock s){ super(l, s); } public void run(){ while(true){ stock().supply(); inc(); // 納品した個数を記録 sleeping(1000); 双方Threadのサブ(サブ)クラス

以上