Personal tools
You are here: Home ブログ 井上 Javaのオートボクシングでバグ寸前
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent entries
Apache2.4のリリース予定は来年(2011年)初め(あくまで予定) inoue 2010-12-23
Herokuの発音 inoue 2010-12-20
雑誌記事「ソフトウェア・テストPRESS Vol.9」の原稿公開 inoue 2010-12-18
IPA未踏のニュース inoue 2010-12-15
労基法とチキンゲーム inoue 2010-12-06
フロントエンドエンジニア inoue 2010-12-03
ASCII.technologies誌にMapReduceの記事を書きました inoue 2010-11-25
技術評論社パーフェクトシリーズ絶賛発売中 inoue 2010-11-24
雑誌連載「Emacsのトラノマキ」の原稿(part8)公開 inoue 2010-11-22
RESTの当惑 inoue 2010-11-22
「プログラマのためのUXチートシート」を作りました inoue 2010-11-19
「ビューティフルコード」を読みました inoue 2010-11-16
Categories
カテゴリなし
 
Document Actions

Javaのオートボクシングでバグ寸前

Javaの同期処理の説明のために以下のようなコードを使いました。synchronizedを説明するため以外に意味のあるコードではありません。

class MyWorker implements Runnable {
    private static final int LOOP_NUM = 10000000;
    private MyCounter counter;
    MyWorker(MyCounter counter) {
        this.counter = counter;
    }
    @Override
    public void run() {
        for (int i = 0; i < LOOP_NUM; i++) {
            counter.increment();
        }
    }
}
    
public class MyCounter {
    private int count;

    public synchronized void increment() {
        count++;
    }

    public void doit() throws InterruptedException {
        Thread t1 = new Thread(new MyWorker(this));
        t1.start();
        Thread t2 = new Thread(new MyWorker(this));
        t2.start();

        t1.join();
        t2.join();
        System.out.println(count);
    }
    
    public static void main(String[] args) throws InterruptedException {
        MyCounter my = new MyCounter();
        my.doit();
    }
}

この後、synchronizedには別の書き方もあるという説明をするため、countの型が参照型のIntegerなら次のようにも書ける、と展開しようと思いました。

public class MyCounter {
    private Integer count = 0;

    public void increment() {
        synchronized(count) {
            count++;
        }
    }
    以下省略

分かる人には一瞬でしょうが、これは期待どおりの同期処理をしません。答えを直接書くのは野暮なので、分からない人にヒントだけ書きます。Integerは不変型なのでcount++でオブジェクトの状態を変更していません。

以前(http://dev.ariel-networks.com/Members/inoue/terror-bugs2)もオートボクシングで恐いバグを経験しましたが、オートボクシングはJavaに気づきにくいバグをもたらします。

FindBugsを通してみると、 http://findbugs.sourceforge.net/bugDescriptions.html#DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE

DL: Synchronization on boxed primitive could lead to deadlock

の警告を出してきました。

もしふたつのスレッドが次のコードを実行するとデッドロックする可能性があります。まあ、こんなコードは書きませんが。

// スレッド1
Integert i1 = 1;
synchronized(i1) {
    increment();
}
  
// スレッド2(MyCounterクラスのメソッドを仮定)
Integert i0 = 0;
synchronized(i0) {
    count = 1; 
    increment();
}

Javaで試験問題を作る時はFindBugsを参考にするのがよさそうです。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/terror-bugs3/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.