ポインタが欲しいときがある

C++病。別々のスレッドから同じ位置にあるメモリの情報を見たい。
というときに、e_c_e_tは、思いつくままにポインタでガシガシメモリをいじくるのだけれど、
javaの場合だと、下のようなクラスでスレッドを書くのが正しい流儀のようだ。


// MFCで書くとこういう感じだろう
class Hoge{
char vals[1000];
HANDLE mutex;
// コンストラク
Hoge(){ mutex = CreateMutex(0, FALSE, 0); }
// スレッドの中からも外からも触られる関数
void setChar(int i){
WaitForSingleObject(mutex, INFINITE); // 同時にアクセスされるのを防ぐための排他
vals[i] = 'A';
ReleaseMutex(mutex); // 排他の開放
}
// スレッドを起動する関数
void kick(){
CWinThread * thread = AfxBeginThread(tfunc,this);
}
//スレッドとして起動される関数
static UINT tfunc(LPVOID param){
Hoge * thread_hoge = (Hoge *)param;
thread_hoge->setChar(1);
}
};

Hoge * a = new Hoge(); // オブジェクト作成
a->setChar(10); // スレッドの外から触る。
a->kick(); // スレッド起動

上をjavaで書くと、こういう感じか

public Hoge extends Thread{
private volatile char[] vals = new char[1000];
public Hoge(){}
// スレッドの中からも外からも触る関数
public void setChar(i){
synchronized(vals){ // 同時にアクセスされるのを防ぐための排他
this.char[i] = 'A';
}
}
// スレッド起動関数
public void run(){
this.setChar(1);
}
}
//実行
Hoge a = new Hoge(); // インスタンスの作成
a.setChar(10); // スレッドの外から触る
a.start(); // スレッド起動
随分簡単になった、ように、見える、が、このコードにたどり着くまで時間がかかった。
問題なのは(というか、大きくつまづいたのは)、スレッドの中からメンバ関数へアクセスする部分だ。
VC++だと、スレッド起動時のポインタの渡し方を間違えなければ、そこから
たどれる情報はプログラマの責任において、(ある程度)好き勝手に触れる。
つまり、スレッドローカルなメモリと、スレッドの外側のメモリとのやり取りは
このポインタ経由で自分で管理できる。
けれど、javaの場合はどうやら、スレッドを起動すると勝手にスレッドローカルな新しいメモリ空間が作られるらしい。
この(勝手に作られる)スレッドローカルなメモリ空間の値と、スレッドの外側のメモリ空間で、共通のデータは通常は使えない。
使えるようにするには、使いたいデータの宣言にvolatileをつけて宣言する。
コンパイルして確かめたわけじゃないので、間違ってたら失礼)