blog画像が表示されないページは、元画像を間違えて削除してしまっているためです。データが残っていないので、想像力で補ってください。2016/07/12[java]非同期に翻弄される人間、いろいろあると、不信感に襲われてしまいますな、いやいや。状態変数のチェックをメソッドの始まりで2回やって、そこまでチェックをくぐり抜けたら処理する、とやってたのだけど、すり抜けるのをはじめて目にしてしまってね。何日もテストして無事だったのに、なんでいまさらーっ?タイトルからわかるように、非同期で状態変数を変更する処理が呼ばれていたのですな。setVal;}★のところでディスパッチして、別メソッドが呼ばれて、チェック1で引っかかるような値が代入されてしまったのですよ。チェック1で引っかかる値はチェック2でも引っかかるので、先にチェック1で見て、既にこの状態だったらOK、ということだったのだ。いやいや、そのタイミングでディスパッチできるとは、やりますな。教科書にあるような失敗例だったので、教科書にあるような対処法で済む。Javaにはsynchronizedという便利なものがあるので、それを使えばよいだろう。例では短く書いているけど、本当はもっと長くて、メソッド自体をsynchronizedしてしまうとデッドロックしてしまうのだ。「実行()」の手前までディスパッチを禁止してくれれば良いのだ。そんなにひどいことをさせられないのか、synchronized(オブジェクト)、みたいな書き方なのですな。「このオブジェクトに掛けて、排他してやる!」みたいな意気込みになっているように思える。finalじゃないといかんようだ。オブジェクトが変わってしまうと排他にならないからか。setVal;}}で、問題はどちらかというとこれからで、本当にこの対策で現象が出なくなるのか?だ。実は別の場所の方に問題があって、これではだめなのかもしれない。再現性が元々かなり低いので、自然に発生するのを待つことはできないだろう。するかというと、割込が入りやすいように、★のところにThread.sleep()を入れた。synchronizedを外した状態で動かして、発生していたエラーと同じことが起きることを期待する。synchronizedを付けて、エラーが起きないことを期待する。うん、今回はうまくいったようだ。ねぇ、作りをあれこれ変えていったので、実はこういうチェック無しでもいけるんじゃないの?という気がしている。その決断を下す勇気がないというか、判断ができないというかで、現状維持しているというところ。ここら辺は、付け焼き刃の知識じゃダメだなー、と思う。空気感が読めないというのかね。件のコメント:コメントを投稿コメントありがとうございます。申し訳ないですが勝手に削除することもあります。コメントを投稿できるのは、このブログのメンバーだけです。