Civ4 日記 その1

[普及版]シヴィライゼーション4 【完全日本語版】

[普及版]シヴィライゼーション4 【完全日本語版】

Steam で civilization シリーズが値下がりしたのでついつい civ 4 を買ってしまった.友人から面白い,廃人ゲーと聞いていたのに軽い気持ちで買ったことを後悔している.本当に面白い.久しぶりにはまってしまった.

このゲームを一言でまとめると,文明を一から作り出すゲームである,文明の発展には,土地の開拓,資源徴収,人口増加,技術・文化の発展,他国との外交・戦争など本当に複雑な要素が関係している.それら複雑な要素を絶妙なバランスでブレンドされているのがこのゲームである.

とりあえず今はゲーム内の要素を把握するために,下記のような動画やドキュメントで勉強中である.これらの資料を見ることで,ようやく普通に AD 2050 までプレイすることができた,

とりあえず最低限把握しておきたいこと

始めた当初は何回か文明が途中で滅ぼされてしまった.初めて AD 2050 まで到達するまでに気をつけたことをメモしておく.

軍備

文明開始直後ならともかく,AD 1500 を過ぎた頃から周辺国はメキメキと軍備を整える.一度攻め込まれると軍備関係の生産がとてもじゃないのが追いつかないので,領土が広がるたびにちょくちょく生産しておく.そして,新たな軍備の生産が可能になれば,逐次各ユニットのアップグレードをおこなっておけばそれほど攻め込まれることもない.

外交

とりあえず戦争にならない程度に付き合っておけば良いのか.最初は英語をちゃんと読んでおらず無視しまくっていたら攻めこまれてゲームオーバー,なんてことが多かったのでとりあえず従順なしもべとなっていた.こちらが持っていない技術も交換してもらえるし.ただ相手にも技術が渡るので,発展を助けている形になっているのかもしれない.

幸福度

低すぎると内乱が起こるので重要.ゲーム開始当初は全く気にしてなかったが,これを意識した生産を行うことで AD 2050 まで辿りつけた.とりあえず宗教施設をちょくちょく作っていれば安心か.ちゃんと生産物の説明を読みつつ上げていきたい.

今後の目標

現在のプレイスタイルでスコア1位にはなれるものの,内訳は文化一択他は糞というスコアである.今後はバリバリ軍国主義プレイや大海原に繰り出すプレイなど色々試してみたい.

妄想は膨らむばかり.

「増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編」第三章『Guarded Suspension』読書中

時間がなかなかとれないものの,日々少しずつでも進めている.

現在読んでいる章は『Guarded Suspension』というサブタイトルが付けられている.

Guarded Suspension パターンは,スレッドを待たせてインスタンスの安全性を守ります.それはちょうど,配達員を玄関先で待たせて自分のプライバシーを守るのと似ています.

とあるように,あるスレッドが実行されている際には他のスレッドを待たせておき,スレッドの実行が終了してから待っているスレッドの実行にとりかかるというものである.

サンプルプログラムでは,リクエストを行うクライアントスレッドとそのリクエストを処理するサーバースレッドを実装する.両者ともに,リクエストを格納するキューを使用する.クライアントはリクエストをキューに追加し,サーバーは追加した順番通りにキューからリクエストを引き出し処理を行う.ちなみに UML ではこのようなサーバー・クライアントスレッドのことを能動オブジェクト (active object),キューのことを受動オブジェクト (passive object) と呼ぶらしい.

当然キューにリクエストがなければ処理は実行できない.キューにリクエストが存在するということがガード条件になっている.このように,ガード条件が満たされるまでスレッドは処理を待たされるわけである.具体的な処理としては,キューにリクエストがない場合は,サーバースレッドは while 文とwait() によって処理の実行を待ち,クライアントスレッドがリクエストを追加し,notify/notifyAll でそれを知った上で処理の実行を開始する.

「増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編」第二章『Immutable』読了

第二章読み終わった.

内容的にメモっとくべきところは前回記事くらいだな,という感じ.

それと,演習問題で synchronized を使用した場合と,immutable な synchronized を使用した場合とのパフォーマンス比較を行った.実際にプログラムを実行し,その実行時間を比較するという演習である.その結果,synchronized を使用した場合はそうでない場合に比べて,数百倍の時間がかかるという結果になった.この結果からも,クラスはできるだけ immutable にし,synchronized を使用しないほうが良いということがよくわかった.

Immutable なクラスとスレッドの名称

「増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編」の第二章『Immutable』を読み進めている.簡単に内容を説明すると,排他制御など使わずともそもそもインスタンスが作られてからフィールドの値が変化しないものはマルチスレッドで処理をおこなっても安全性が保証されるというお話である.これは当然で,例えばクラス内で private final で宣言され,setter メソッド (変数値を変更するメソッドの通称)が存在しないならば安全である (オーバーライドされるなど例外は存在するが).これを "Immutable (不変な)" 状態と呼ぶ.

synchronizede をうまくつければ安全性が向上するが,プログラムの処理パフォーマンスを落としてしまう.そこで,そもそもクラスを Immutable に作っておけばパフォーマンスを落とさずにマルチスレッド処理をできる.安易に synchronized を使わず,工夫をこらして堅牢なクラスを作れということか.マルチスレッドプログラミングの勉強はそれ以外の範囲でも役に立つと聞いていたけれど,こういうクラスの作り方の工夫などは正にそれだと思う.

スレッドの名称

本書に乗っていた Thread クラスをオーバーロードした例題プログラムのコンストラクタ内で,以下のような記述を見つけた.

super ( String str );

オーバーロードした Thread クラスのコンストラクタに String 型を渡している.恥ずかしながら,これが何を意味しているか知らなかったが,どうやらスレッドに str という名前をつけるものであるようだ.
JavaTM 2 Platform Standard Ed. 5.0 "Thread"

そういえば,スレッド関係のプログラムを実行した際に,

Exception in thread "Main"

とか出てたな.

「増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編」 第一章『Single Thread Execution』読了

第一章読了.ここではひとつのスレッドによる実行をテーマにしていた.大雑把に言えば排他制御を行いつつ"オブジェクトが壊れないように"プログラムを動かすということである.これには主に synchronized が役に立つ.

この章で覚えておくべきだと思った点をメモしておく.

スレッド開始と実行順序

スレッドが実行される順序は,必ずしもプログラム上で start() をした順序通りにはならないらしい.
スレッドの排他制御と実行順序

SharedResource 役とデッドロックの条件

SharedResource 役は,複数のスレッドからアクセスされるクラスです.SharedResource 役はいくつかメソッドを持ちますが,そのメソッドは,以下の2種類に分類されます.

  • safeMehtod - 複数のスレッドから同時に呼び出しても,もともと問題のないメソッド
  • unsafeMethod - 複数のスレッドから同時に呼び出されては困るので,ガードしなければならないメソッド

(61 ページから引用)

マルチスレッドプログラミングでは unsafeMethod の取り扱いに気を付けなくてはならない,とりわけデッドロックは頭を悩まされる問題である.

デッドロックが発生する条件がわかりやすく説明されていた.

  1. 複数の SharedResource 役がある
  2. スレッドが,ある SharedResource 役のロックをとったまま,他の SharedResource 役のロックを取りに行く.
  3. SharedResouce 役のロックをとる順序が決まっていない (SharedResource が対称である)

(64 ページから引用)

この3つの条件を満たした場合,デッドロックが発生する.逆に言えば,このうち一つでも条件を崩してやればデッドロックを解消させることができる.本書では「ナイフとフォーク」のプログラム例を用いてデッドロックが起こる場合とそうではない場合がわかりやすく説明されていた.

Semaphore

補講として取り扱われていた計数セマフォ.Single Threaded Execution は,「たった一つのスレッド」だけが実行するパターンだが,計数セマフォによってより一般化し,「最大で N 個のスレッド」までは実行するパターンとなる.

java.util.concurrent パッケージに含まれる Semaphore というクラスを使用する.コンストラクタでリソースの数を指定し,acquire メソッドでリソースを確保する.スレッドを使用した後,リソースを解放するのが release メソッドである.このrelease メソッドは,確実に実行されるべきなので try {} finally {} 構文を使用するべきだろう

総評

まだまだマルチスレッドプログラミングの入り口なのでわからないことばかりだ.章を進めていくことで今抱えるモヤモヤが解決されると信じている..

マルチスレッドプログラミングの必須条件

「増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編」のイントロダクション部分で重要な概念が書かれていたのでメモ.『マルチスレッドプログラミングの評価基準』という節で,そのタイトルが示すとおりマルチスレッドプログラムを書いた際に検討すべき 4 点について簡潔にまとめてある.その中でも特に重要な "安全性" と "生存性" について覚書き.

安全性

安全性 (safety) とは,オブジェクトを壊さないことです.これは正しく動くプログラムに必須の条件です.
(44 ページより引用)

これはつまり,オブジェクトの設計者が意図したとおりにプログラムが動作するかということ.動作しない例としては,排他制御を行わずに複数スレッドを使ってある変数の処理を行った場合にデータの不整合が起こるなどが挙げられる.マルチスレッドプログラミングでは最新の注意を払わなければならない点である.複数のスレッドが利用しても安全性が保たれることをスレッドセーフと呼ぶらしい.

ただし,何でもかんでも安全性を追求すればいいとうものでもない.詳細については後述の生存性にて説明する,

生存性

生存性 (liveness) とは,必要な処理はいつか必ず行われることです.これも正しく動くプログラムに必須の条件です (生存性の代わりに活動性という訳語が使われる場合もあります).
(45 ページより引用)

安全性が守られているからといって,必ずしもプログラムがちゃんと動作するとは限らない.極端な話,プログラムが途中で動かなくなればオブジェクトの状態が変化することもなく,安全性は高いといえる.しかし,このような意図した処理を行わないプログラムに意味はない,そいういった意味で,この生存性という評価基準もマルチスレッドプログラミングを考えていく上で重要な概念である.

生存性と安全性のトレードオフの具体例としてデッドロックが挙げられる.例えばメソッドに synchronized を付加すれば安全性は保たれるかもしれないが,複数のスレッドが相手のロック開放を互いに待ってしまうような状態が起こり得る.このような状態をデッドロックと呼び,避けなければならないものである.

以上の2つがマルチスレッドプログラミングを行う上で必須の条件である.この他にも再利用性やスループットや応答性などのパフォーマンスも評価基準として考えられるが,とりあえず "安全性" と "生存性" の高いプログラムを書けるようになりたい.

Mac に Windows 8 を導入

Gizmodo の記事を参照しながら特に理由も目的もなく入れてみた.ここで Japanese 64bit をダウンロードして DVD に焼き,あとは Bootcamp に任せておけば自動的にインストールしてくれる.ところどころでプロダクトコードなどの入力を求められるけど.プロダクトコードは Gizmodo に掲載されていたものを使用したけれど,勝手に使っていいものなのだろうか.

タブレット製品などのタッチパネルを意識した作りなんだろうが,かなり UI が変わっていてびっくりした.面白いけど Office 製品をバージョンアップした時の様になれるまで相当時間掛かりそう.