2008年8月アーカイブ

ソフ開の模試を受けてきた。
講師の方も問題も全く前回と同じだったのですが...解けなくなってる ;´Д`)
こりゃーやべぇー。

休み中はなるべく勉強するようにしないとなぁ...。

こっから先はノートにメモってないんだよなぁ。
ちょっと読み直しつつかいてく。

--------------
48.可変データへの共有アクセス
Javaはlongやdouble型以外ならば読み書きがatomic(不可分)であることが保証されている。
(Tigerでjava.util.concurrent.atomicパッケージが追加された。参考:「Tiger (Java2 SE 1.5) で追加された並列プログラミング機能」)
だからといって、データの読み書きがatomicなら同期いらないじゃんということにはならない。
→Javaのメモリモデルではあるスレッドが変更した値を他のスレッドが参照できるとは限らない。

マルチスレッド対応でないシリアルナンバー生成器の例。

private static int serialNumber = 0;
public static int getSerialNumber(){
  return serialNumber++;
}

マルチスレッド対応にさせるのならデータを書き換える部分をsynchronizedにする。

private static int serialNumber = 0;
public static synchronized int getSerialNumber(){
  return serialNumber++;
}

他にも可変データにvolatile修飾子を付けるという手もある。
本では例として外部にフラグを公開して他のスレッドからオブジェクトの振る舞いを変更するクラスを挙げている。
まず、synchronized版。

private boolean stop = false;

public void run(){
  boolean done = false;
  while(!stopRequested() && !done ){
    //処理
  } 
}

public synchronized void requestStop(){
  stop = true;
}

private synchronized void stopRequested(){
  return stop;
}
上記と同じ振る舞いをするvolatile版。
private volatile boolean stop = false;

public void run(){
  boolean done = false;
  while(!stopRequested() && !done ){
    //処理
  }
}

public void requestStop(){
  stop = true;
}

private void stopRequested(){
  return stop;
}

そうするとさっきのserialNumberもvolatile宣言すれば終わりなのかという疑問も出てくるが、結果を先に言うとこれはアウト。
serialNumber++;は見た目は1ステップだが、本当は内部でデータの読み込み・加算演算・書き込みの3stepからなっているのでこれらをsynchronizedブロックでまとめてatomicにしないとマズイ。

基本的にvolatileが使えるのは上記のようなbooleanフラグぐらいなものだろう。
もっと応用的な使い方はIBMの記事、「Javaの理論と実践: volatile を扱う」参照。

IBMの記事は良記事が多い。synchronized とvolatile の違いをうまくまとめている。

volatile 変数は、可視性という特徴は synchronized と同じですが、synchronized のようなアトミック性を持っていません。これはつまり、スレッドは自動的に volatile 変数の最新の値を見るということです。
また本章の最後の方ではLazy Initialization(怠けた初期化; 必要になるまでオブジェクトを生成しないこと)のマルチスレッド対応方法についての手法もまとめている。

1.static初期化をしてLazy Initializationを諦める方法
2.Lazy Initialization処理が書かれているgetXXX()をまるごとsynchronized 化。
 →同期化のコストはかかるが、一番確実。早期化のコストを減らそうとして二重チェックイデオムに走らない。
3.オンデマンド初期化ホルダークラスイデオム
 →同期化コストがかからない。けどインスタンスフィールドには適用できない。
あと3.は個人的に読みづらい印象を受けるなぁ。
だいたい、オンデマンド初期化ホルダークラスイデオムの検索結果 1 件中 1 - 1 件目 (0.29 秒) だよ。あまり使われてないっぽいな。


--------------
49.同期とパフォーマンス
並列性を向上させるために同期されたブロック内の処理量は少なくするようにさせる。同期が必要ない処理はsynchronized の外に出す。

特に同期ブロック内でpublicやprotected等、オーバライド可能なメソッドの呼び出しは行わない。(=制御をクライアントに委ねてはならない)オーバライドの仕方によってはデッドロックの原因にもなる。(p186-187)

クラスが本当に複数のスレッドから使われるものなのか意識して設計する。
例えばStringBufferは大抵の場合、複数のスレッドで共有なんかしないので同期のコストは本来ならば不要。
(1.5 Tiger 以降ならStringBuilder使った方がいいね。)
同期を必要としないと判断したなら、そのことをドキュメント化することを忘れずに。

同期が必要な場合、同期が不要な場合、どちらでも多く必要とされるクラスの場合は?
→まず、同期無し版を作成。その後、作成したクラスの全てのメソッドを適切な同期ブロック内で呼び出すラッパークラスを同期アリ版としてリリースするのが適切。


--------------
50.waitループ
wait()は以下のように呼び出す。
synchronized (obj){
  while(条件が成立していない)
    obj.wait();

  //条件成立時に行う適切な処理

}

ループにすることで間違った通知(notify)から保護することが出来る。
全てwaitループイデオムを使ってwaitしているなら、notifyよりもnotifyAllを使って通知した方が正しい(安全)。通知内容に関係のない待ちスレッドは再び待機状態に入り、起こしたいスレッドは必ず起きるからだ。ただし、待ちスレッドが多い場合、パフォーマンスに悪影響を及ぼす。


--------------
51.スレッドスケジューラに依存するプログラムは書かない
・なかなか実行されないスレッドがあっても、Thread.yield(); とかして譲ったりはしないこと。JVMの実装により、その後の動きが異なるので移植性の低いプログラムとなる。
・同様にスレッドの優先順位も変更しないこと。

Thread.yield(); の唯一の使い道→テスト時に意図的に実行可能状態にあるスレッドを走らせてバグが出ないか調べるぐらい。


--------------
52.スレッドの安全性をドキュメント化しろ
まぁ、当たり前と言えば当たり前の話。
本ではスレッド安全性のレベルを5段階(immutable, thread-safe, conditionally thread-safe, thread-compatible, thread-hostile)に分け、これらを記述することを推奨している。
詳しくは「スレッド・セーフの特性について」を参照。

conditionally thread-safe(条件付きスレッドセーフ)の場合は特にドキュメントの書き方に気を付ける。
例えばクライアントがロックを取得しなければならないのならば、どのように取得すればよいのか、サンプルコードを記載する。

スレッドセーフクラスでクライアントにロックオブジェクトを提供する場合、柔軟性と脆弱性が紙一重な点に注意する。

//サービス拒否攻撃(lockObjを提供したクラスはもう動かない)
synchronized (lockObj){
  Thread.sleep(Integer.MAX_VALUE);
}
クライアントにロックを委ねている条件付きスレッドセーフクラスは常にこの攻撃にさらされる。
スレッドセーフクラスでの回避方法→プライベートなロックオブジェクトを使用。
private Object lockObj = new Object();

public void f(){
  synchronized (lockObj){
    //処理
  }
}

(そーいえばこのようなコードをどっかのクラスで見たなぁ...忘れてしまったが。)


--------------
53.スレッドグループは使わない
クラスjava.lang.ThreadGroupのこと。
唯一uncaughtExceptionぐらいは使えるらしいが、Tiger以後はThread.UncaughtExceptionHandlerインターフェースを実装する手法があるらしいので(参考:Tigerを使いこなす: スレッドでのデフォルト例外処理)マジで使うことはないクラスかも。

今日は代休だったので、午前中に眼科に行った。
どうも最近疲れてくると左目だけがやたら痛くなるので、そろそろメガネで矯正もできんほど両目の視力に差が出たか?と思ったんだけど...。

両目の視力の差は以前と変わらないらしい。ただ、その差を脳で埋めれる程もう若くはないよねぇと言われ...若干ショック(´Д`;
24はもう若くないのですか。

やっぱりコンタクト+プリズム付きメガネの方が楽だと言われたので、遂にコンタクトにすることにした。(決心に2年以上かかってるな)
1,2回ほど出し入れの練習をしたが...ムズイ。 ;´-ω-)特に取るとき。怖くて目なんか掴めねーよ。

ただ一回装着するとスゴイなコレは。小学生のときにもどったような感覚。メガネを付けているあの感覚無しで遠くのものがよく見えるというのは面白い。けど今度は近くのモノが見づらくなった。急に老眼になってしまったかのようだ。

しばらくは慣らすという意味でコンタクトだけになるが、コレ大丈夫かなー。近くのモノがぼやけるので、仕事に支障がでないかちょっと心配。まぁ、2週間の我慢か。

千葉スターズ

大変クオリティが高い。

3D性能向上とハイエンド向け機能を実装した「AMD 790GX」より5DMark05のグラフ

AMD 780G 3523
AMD 790GX 4569

以前自作PCでベンチしたX800 無印の結果が3808。
CPUの差もあるんだろうけど、3年も経つとオンボードに負けちゃうのねぇ...。 つД`)

何故かこの動画に取り憑かれてしまった

総武線が真っ黄色だった頃が懐かしい。確か高1ぐらいで急に見なくなっちゃったんだよなぁ。

モーター音だけ聞きたい人用

今ではインドネシアで頑張ってるらしい。[参考]
なんで行き先が「府中本町」やら「新松戸」のまま残ってるんだw

自分はFreeBSDからunixな世界に入ったため、以前はtcshをよく使っていた。
バイトでbona先生と知り合い、そこでzshの存在を初めて知り、あまりの高機能さにzshに移ったわけだが、どうしてもコレだけはtcshの方がイイよなぁと思う箇所が一個だけあった。

それは矢印キーによる履歴検索。
例えば
$grep hoge hoge.txt
$cat hogehoge.txt
と打った後
gre↑と入力するとtcshでは気を利かせてgreから始まる以前の入力grep hoge hoge.txtが出るのに対し、zshはデフォルトで直前のcat hogehoge.txtが出る。

この部分だけがtcshっぽかったら最高なんだけどなぁと思って今日調べてみたら、(やっぱり)この挙動をカスタマイズできるらしい。


www.crimson-snow.net/tips/unix/zsh.htmlより

# コマンド履歴の検索機能の設定
# ^[ は「エスケープ」
# viなら Ctrl-v ESC
# Emacsなら Ctrl-q ESC
# viで編集する場合
# 上2行は Ctrl-v を押下した後、希望のキーを押下
# 下2行は「エスケープ」の後にキーの端末コードを入力
autoload history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end
bindkey "^[[A" history-beginning-search-backward-end
bindkey "^[[B" history-beginning-search-forward-end

矢印キーの端末コードがどうなるかは環境依存。
cygwinでは^[OA、
FreeBSDにputty経由で繋いだら^[[Aになった。
めんどくさいから2パターンとも書いてた方がイイカモね。

いやーこれでまた快適になった。もっと早く調べておくべきだったよ。

好きな曲をニコニコ動画内で検索すると思わぬ発見をすることがある。

http://nicovideo.g.hatena.ne.jp/Lyo/20080820/1219241823

windowsでもunixツール使いたいと思い、cygwinを入れてみた。
coLinuxやandLinuxもアリかなぁとも思ったが、やっぱりインストールの手軽さでcygwinを選んだ。

cygwinなんて大学学部生の頃のC言語学習以来なのだが、パッケージ見て以外とツールが豊富だと言うことに気づいた。
perlも5.10系になってるし、zsh,GNU screen,lvもあるし。

んで、せっかくwindowsの生のファイルに直アクセスできるのだから完全に文字コードをShift_jisに絞って環境構築をしようと言う話。

やったこと。
perlやzsh,GNU screen,lv,vim等をインストール。
.zshrcに
export LANG=ja_JP.sjis
export LC_ALL=ja_JP.sjis
export OUTPUT_CHARSET = sjis
を追記。

更にlvで文字化けしないようlvを"lv -Os"になるようエイリアス追加。
LANG=ja_JP.sjisで文字化けが解消するかと思ったらlsがまだ文字化け。
lsを"ls --show-control-chars"になるようエイリアス追加。ついでに--color=autoも追加しておくと見やすいかも。
diffをcolordiffに置き換え。make installでは無理だったので手動コピー。

.vimrcに
set termencoding=sjis
set encoding=sjis
追記。

次にプログラムのエラーメッセージも日本語化する。(参考:Cygwin 覚書 -- Ray:雑学事典)
devel - gettext-develをcygwinに追加インストール。
日本語メッセージの文字化けに対応する」からsjis化シェルスクリプトを頂いて実行。

ここまでやってもfindコマンドの出力が文字化けするという現象が発生した。
→print0オプションを付けると何故か文字化け解消。ワケワカラン。

引数を1行ずつ出力するだけのperlスクリプト(print_args.pl)を作り
find . -print0 | xargs -0 perl print_args.plとかやったら普通に出力された。
というか-print0と-0を抜かしても普通にokだった。一回他のコマンドに流してやれば特に問題なかったぽいので、少しとほほな対処法だがまぁいいか。

cygterm+puttyも試してみたが見事にコケた。どうもネットワークが絡むと仕事場の環境ではダメっぽい。むぅ。

つい最近までとある自分が属するプロジェクトがリリース直前だったので日記を書く暇がないほど忙しかったわけですが(言い訳)先日リリースが終わり、かなり落ち着いてきた今日この頃。

というか落ち着きすぎて今日は仕事らしい仕事をほぼ何もしてねぇ ;´Д`) いいのかこれで
明日からはバッチを作る仕事に就くことになりそう。

---

SAPコンサルが多用するフレーズ - 実践!戦略的IT経営が大変面白い。

CiNii - ぷよぷよはNP完全

タイトルだけで読んでみてぇー と思った論文はこれが初めてだ。

すっげー面白いと思ってたものが遂に...!!

遊び方
http://maps.google.co.jp/にアクセス
g_maps_s.jpg
1.ストリートビューというのが今回新しく追加されているので選択。
ちなみに青い部分が見れるところ。いつのまにか主要都市圏ほぼ全てカバーだよ。すげーよー。

2.地図を拡大すると人型アイコンが出てくるので見たい道路のとこまでドラッグアンドドロップ。もしくは見たい箇所の道路をダブルクリック。

(渋谷駅前を選んだところ。)
g_maps_s2.jpg
3.写真をマウスでグリグリしてみて遊ぶ。


いやー、いつの間にか自宅の前にgoogleのカメラ積んだ車が通ってたんだなぁ...。ちょっと感動。

このアーカイブについて

このページには、2008年8月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2008年7月です。

次のアーカイブは2008年9月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ

OpenID対応しています OpenIDについて
Powered by Movable Type 7.9.3