ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Javaの課題丸投げコミュの排他

  • mixiチェック
  • このエントリーをはてなブックマークに追加
おはようございます。

ごく初歩的なことなのでしょうけれど

Person というクラスがあるとします。人はみんなそれのサブクラスです。
そこにFriendとそれをextendしたBoyFriendがあるとします。

public class Person{
}

public class Friend extends Person {
}

public class BoyFriend extends Friend {
private Friend myGirlFriend;

public void setGirlFriendForce(Friend friend) {
if (parents.allow(friend) {
myGirlFriend = friend;
}
}
public Friend getGirlFriend() {
return myGirlFriend;
}
}

これは動きそうです。しかし、スレッドセーフではありません。
スレッド1 aBoyFriend.setGirlFriendForce(me.this);
girlFriend = (GirlFriend) aBoyFriend.getGirlFriend();
スレッド2 aBoyFriend.setGirlFriendForce(anotherGirl.this);
girlFriend = (GrilFriend) aBoyFriend.getGirlFriend();

私がボーイフレンドの属性として私を設定しても、結果、anotherGirlが勝つことが発生し得ます。
更に、仮に
private List <GirlFriend> girlFriendList;
にした場合、私が何番目になるかまでは分かりません。
個人的にとても困ります。
まぁ、心変わりしたのであれば分かりますけれど。
どのようなアプローチがとれるものでしょうか?
よろしくお願いします。

コメント(9)

そもそも、上記のコードでは、排他処理を行うようにしても、後勝ちするだけだと思います。
また、複数のスレッドで動かしている限り、setGirlFriendメソッドの呼び出し順を固定することは出来ません。(正確には出来ますが、それなら複数スレッドにする意味がありません)
おはようございますわーい(嬉しい顔)

私の書いたコードが複数スレッドで実行されると結果は不定になるのではないでしょうか?

Thread1
aBoyFriend#setGirlFriendForce(me.this)
    ここで違うスレッドが実行権を取得

Thread2
aBoyFriend#setGirlFirendForce(anotherGirl.ths)
aBoyFriend.myGrilFriend = anhoterGirl.ths;
aBoyFriend#getGirlFriend == anotherGirl.this
で安心していても

     Thread1復活
  aBoyFriend.myGirlFriend = me.this;
aBoyFriend#getGirlFriend == me.this


仮に
public interface Updatable {
public boolean isUpdatable();
public void setUpdatable(boolean updatable);
}

public class Friend implements Updatable {
private boolean updatable;
public boolean isUpdatable(){
return updatable;
}
public void setUpdatable(boolean updatable){
this.updatable = updatable;
}
}

public void setGirlFriendForce(Friend friend) {
if (isUpdatable()) {
if (parents.allow(friend) {
myGirlFriend = friend;
}
}
setUpdatable(false);
}

if (!aBoyFriend.isUpdatable()) {
aBoyFriend.setUpdatable(true);
}
aBoyFriend.setGirlFriendForce(me.this);
の様にしても、aBoyFriendの状態が分からないことに代わりがありません。

public interface Commitable {
public void commit(Friend friend);
}

public void setGirlFriendForce(Friend friend) {
if (parents.allow(friend) {
myGirlFriend = friend;
myGirlFriend.commit(this);
}
}

の様にしても私のように嫉妬深い場合には意味がなさそうです。
public class IntimateFriend {
private List intimates;

public void setGirlFriendForce(Friend friend) {
if (!intimates.contains(friend)) {
intimates.add(friend);
}
if (parents.allow(friend) {
myGirlFriend = friend;
fireGirlFriendChangedEvent(friend,intimates);
}
}

このようにした場合ですと、よけいにスレッドに関して気を配らなければならないように思われますし、
ほとんどの場合では必要のない処理にも思えます。しかも、プライバシーの侵害です。

結局のところ
public class BankAccount extends Account {
double amount;

public double getAmount() {
return amount;
}
public void 出金(Account anotherAcount) {
double total = anotherAccount.getSubtotalt();
amount -= total;
}
public void 入金(Account anotherAccount){
double total = anotherAccount.getSubtotal();
amount += total;
}
}
getAmount();
出金();
入金();
はそれぞれアトミックでなければならないハズです。

ところが、上記BoyFriendクラスはアトミックであることを全く保証していません。
どのようなアプローチがとれるものでしょうか?
よろしくお願いします。
おはようございますわーい(嬉しい顔)

仮に
BoyFriend#setGirlFriendをしたスレッド、もしくは私自身を引数とした場合は同一であることを保証する。

この場合ですと、あるBoyFriendのインスタンスは場合によって挙動を変えなければなりません。
aBoyFriend#getGirlFriend()==me.thisを保証する。

しかし、それで業務が適切であるかは実際のところ私にも分からないことなのです。

BoyFriend#setGirlFriendForce(Friend girlFriend)と
BoyFriend#getGirlFriend()

の間にどんな割り込みがあってもおかしくありません。
しかし、ある個人としてみると
aBoyFriend.setGirlFriend(me.this);
を呼び出したなら当然のように
aBoyFriend.getGirlFriend() == me.this
を期待されるものでもあります。(女たらしの場合には別クラスが必要とか)

setGirlFriendForceでストアした値がgetGirlFriend()にてロードする値と
違う場合が存在する。(前述のように後勝というルールすらありません)

私自身は、勉強中の身分ですので分からないことが沢山なのですけれど、
このような事例において、考えられる良い方策はあるのでしょうかというのが
そもそもの疑問なのです。

ですから、仕様も含めて妥当な決めごとを質問しております。
それはトランザクション単位の切り分け方等かも知れませんけれど、
よろしくお願いします。

初めまして。
スレッド間共有の問題はsynchronized等で更新を保証すれば良いと思いますので問題ではないのですよね。
この場合は、どこからでもsetGirlFriendForceを呼び出してどんどん更新されてしまうという宿命なので、
setGirlFriendForceを行った後の次にgetGirlFriendを呼び出す場合には都度呼び出し側が検証する必要があるのではないでしょうか。(例えばgetGirlFriendで取得したFriendのインスタンスが自分であるかどうかをチェックする等。)

関係ないですが、
>public void setGirlFriendForce(Friend friend) {
>if (parents.allow(friend) {
>myGirlFriend = friend;
>}
>}

は、ガールフレンドとして無理やりセットして親が許可すれば無事OK、のような話なのでしょうか。
これ面白いなぁ。
おはようございますわーい(嬉しい顔)

授業での課題は業務定義と実装で、処理系としてJavaなのです。
つまり、私達グループは業務定義でつまずいている段階なのですあせあせ(飛び散る汗)

定義を始めているうちに「男は信用ならない」と言うことが問題になり
「女も信用がならない」というようなことも持ち上がり「人は信用ならない」
という当たり前かつ複雑な定義に挑んでいるところです。

上記のBankAccountの場合ですとそれぞれの業務は分割が可能であり、
且つ相手も信用ができるという前提に立つことができます。

しかし、このBoyFriendクラスは「信用できない」クラスとしか成り立たないのか?
それとも、ある程度の信用を保証することができるのか?ということが
テーマになりつつあります。

実際Parentについても議論が噴出していて、(男の子に聞いて大丈夫というのが信じられない)
上にaParent#allowがbooleanを返却できるか?アトミックか?変更可能属性を持つか?
等、様々に(変な)議論をしています。

で、仮にsynchronizedをしたとしましょう。
synchronized void setGirlFriendForce(Friend friend) {
if (parents.allow(friend)) {
myGirlFriend = friend;
}
}

synchronized void getGrilFriend() {
return myGirlFriend;
}

これは期待通りに動きません。setGirlFriendForce/getGirlFriendが必ず対で呼ばれるかどうかは分からないからです。

つまり、
thread1 aBoyFriend#setGirlFriendForce(girlFriend1);
thread2 aBoyFriend#setGirlFriendForce(girlFriend2);
thread3 aBoyFriend#setGirlFriendForce(girlFriend3);

mainLooper:
friend = aSurveillance#getGirlFriend();

ただ、この場合でも、変わったことが分かるだけですので
人権侵害といわれようと、
girlFriendChangedEventをfireするのが「正しい」とするのかも知れませんけれど、
EJB側でsetGirlFriend(friend)をして、クライアントにfireするのはおかしいように思えます。
(逆に言うとセッションファザードならイベントのハンドリングをすべし?)

下記のようにしてしまうのも問題が多くありそうです。

public void setGirlFriendForce(Friend friend) {
Catch();
if (parents.allow(friend)) {
myGirlFriend = friend;
}
}
public Friend getGirlFriend() {
return myGirlFriend;
}

protected void Catch() {
synchronized (LOCK) {
LOCK.wait();
}
}



この様なことが現実問題として男性陣に受け入れられるかは疑問です。
そして、同様にGirlFriendクラスも同じにせよというのは受け入れがたいものがあります。
リリースのタイミングも難しいところです。
こんにちは。
そもそも何を入力してどんな結果を期待されているのかがイマイチわからないのでよく分からない回答になってしまいました。
仰られている「業務定義」というのは、実装しながらどんな動きにすれば自然なのかを考えるというニュアンスでしょうか。

あと
>setGirlFriendForce/getGirlFriendが必ず対で呼ばれるかどうかは分からないからです。

なので、setGirlFriendForceを読んだ後に、呼び元がGirlFriendがセットされたのか検証が必要、という事を書きました。

環境はEJBをお使いなのですよね?ていうか、EJBだとかもっと言えばJavaで実装するとかはあんまり関係なく、どのような仕様なのかを明白にするのが先決な気がするのですが如何でしょうか。

あとまた全然関係ないのですが、setGirlFriendForceにはFriendをセット可能なので、男性でもOKなのかな〜というのがちょっと面白かったです。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Javaの課題丸投げ 更新情報

Javaの課題丸投げのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング