- PR -

スレッドセーフ?(return について)

1
投稿者投稿内容
電気ひつじ
会議室デビュー日: 2003/01/15
投稿数: 8
投稿日時: 2003-07-14 21:14
下記のようなコードを書いた場合、引数無しの getCalendar() はスレッドセーフでしょうか?

----------------------------------------------------------------------

public static synchronized Calendar getCalendar(int year, int month, int date){
Calendar cal = Calendar.getInstance();
// cal.clear();
cal.set(year, month, date);
return cal;
}

public static Calendar getCalendar(){
return getCalendar(2000, 0, 1); // (※1)
}

----------------------------------------------------------------------

複数のスレッドから引数無しの getCalendar() が呼ばれた場合に
スレッドAで(※1)の場所において、getCalendar(2000, 0, 1) が実行された後、return される前に
スレッドBの getCalendar(2000, 0, 1) 実行結果が返ってくる可能性は少しでもありますか?
それとも厳密にスレッドセーフと考えて大丈夫でしょうか?
よろしくご教授ください。
みやも
ベテラン
会議室デビュー日: 2002/04/22
投稿数: 74
投稿日時: 2003-07-14 21:38
Calendarがjava.util.Calendarだとすると、
getInstance()はシングルトンのインスタンスを返しているわけじゃない(ですよね?そんなに詳しくないけど、たぶん)ので、スレッドセーフだと思います。
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-07-14 23:30
引用:
電気ひつじさんの書き込み (2003-07-14 21:14) より:

複数のスレッドから引数無しの getCalendar() が呼ばれた場合にスレッドAで(※1)の場所において、getCalendar(2000, 0, 1) が実行された後、return される前にスレッドBの getCalendar(2000, 0, 1) 実行結果が返ってくる可能性は少しでもありますか?

スレッド一つ一つにスタック等が割り当てられているので、その心配はありません。
また、下記の問題を除けば getCalendar(int, int, int) は再入可能である(他のスレッドと資源による問題を起こさないため排他処理無しでスレッドセーフとなる)ため synchronized は必要ありません。(また、synchronized と宣言しても下記の問題は解決できません)

引用:
電気ひつじさんの書き込み (2003-07-14 21:14) より:

それとも厳密にスレッドセーフと考えて大丈夫でしょうか?

基本的に電気ひつじ氏の書かれた部分に関して言えば再入可能ですから、スレッドセーフと言いたいところですが、細かいことを言うと穴があります。Calender.getInstance() がデフォルトのロケール、デフォルトのタイムゾーンを使用する(例えば、Sun の実装では Locale.getDefault(), TimeZone.getDefault() の戻り値が使用される)のですが、これが他のスレッドで変更される(Sun の実装の場合は Locale.setDefault(), TimeZone.setDefault() が呼び出される)場合には拙い事態になる可能性があります。

[ メッセージ編集済み 編集者: お犬様 編集日時 2003-07-15 00:47 ]
電気ひつじ
会議室デビュー日: 2003/01/15
投稿数: 8
投稿日時: 2003-07-15 17:57
java.util.Calendar を使ったサンプルを作ってしまったために
回答しにくい状態にしてしまったようですが、細かいところまで
丁寧に解説していただき大変わかりやすかったです。
ありがとうございました。
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2003-07-18 11:51
import com.nttdocomo.util.*;
import com.nttdocomo.ui.*;
import com.nttdocomo.io.*;

public class game5 extends IApplication {
public void start(){
Main main = new Main();
Display.setCurrent(main);
}
}

class Main extends Canvas implements Runnable
{
Thread thread;
private Image img1, img2;
private int x, y;
private char f = '0';

public void Main(IApplication p){

x = getWidth() / 2;
y = getHeight();

setSoftLabel(SOFT_KEY_1, "終了");

MediaImage mi = MediaManager.getImage("resource:///sol.gif");
MediaImage mj = MediaManager.getImage("resource///bg.gif");

try{
mi.use();
mj.use();
}
catch(ConnectionException e){
}
catch(UIException e){
}

img1 = mi.getImage();
img2 = mj.getImage();

Thread thread = new Thread(this);
thread.start();
}

public void paint(Graphics g){
if(f == '0'){
g.lock();
// g.drawImage(img1, getWidth()/2-8, getHeight());
g.unlock(true);
f = '1';
}
else{
// g.drawImage(img1, x, y);
}
}

public void processEvent(int type, int param){
try{
Thread.sleep(50);
}
catch(InterruptedException e){
}
}

public void run(){
int keypadState;

do{
try{
Thread.sleep(50);
}catch(InterruptedException ie){
}

keypadState=getKeypadState();

if( (keypadState & 1 << Display.KEY_SOFT1) != 0)
IApplication.getCurrentApp().terminate();
if( (keypadState & 1 << Display.KEY_RIGHT) !=0 ) x += 10;
if( (keypadState & 1 << Display.KEY_LEFT ) !=0 ) x -= 10;

repaint();
} while( (keypadState & 1 << Display.KEY_SOFT2) == 0 );
}
}

上の、コメント部分を外すと必ず

java.lang.NullPointerException

なるエラーが出る。これには納得ができない。
原因が全く判らない。
1

スキルアップ/キャリアアップ(JOB@IT)