Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

行ロック(スレッドセーフ)

HashMap等のCollectionsでは、
コレクション全体に対して
スレッドセーフにする場合は、
synchronized〜〜〜等を用いることで、
実現可能と認識していますが、

行(※1)に対するロックがわかりません。
何か良い方法(アイディア)は、ありますでしょうか?

他のAPIで調べたところ、JDK1.5より
ConcurrentHashMapがありましたが、
読み込む際に(Iterator)、コピーして読み込むので
例外(ConcurrentModificationException)がスローされないだけで、行ロックとは関係ありませんでした。

ReentrantLockも見ましたが、あくまでも、行に対するロックを実現するものでは、ないように思われます。

※1
行ロックは、Mapでのエントリに対するロックです。
イメージとしては、エントリ毎に対してロックをかけ、解除できることを想定してます。


17

回答

3643

閲覧

17件の回答

評価

0

getしたものをsynchronizedに使えばいいのでは?

評価

0

名無しさん、ありがとうございます。

確かにそうですね。

出来れば+αとして、複数要求が来て、ReentrantLockを使用してロックを取得し、ロック解除した場合に、要求の順序性を保つことも可能でしょうか?


評価

0

>getしたものをsynchronizedに使えばいいのでは?
それでいいのですか?
Map をロックするか、put するメソッドを shynchronized するのじゃないのですか?

評価

0

MapではなくMapのエントリをロックというから。
ところでメソッドをsynchronizedはできませんよ。
メソッドの宣言にsynchronizedをつけた場合は、synchronized(this)です。

評価

0

synchronizedをヒントに
Mapのエントリに対して、同期をかけることかな?と受け取りましたが、そもそも各エントリに対して、同期って難しいのでしょうか?

synchronized(Mapエントリ){
}

get()であると、同期をかける意味はないので、あくまでもエントリでした。(すいません。)


仕事から帰ってきたところで、今からエントリに対してロックがかけれるか調べています。

割り込んだ素人様へ
Map自体の同期は可能ですが、エントリに対するロックを今考えてます。直接は難しいんですかね?

何か別のアプローチがあるなら、ご教授のほど御願いいたします。

評価

0

具体的に何をしたいのか見えないですね。
例えばMap<String, Map>で値のMapが同期のタネかと思ったんですが、そうじゃないんですかね。

評価

0

すいません、具体的に記載致します。

Map<String, Object>

A  : "KEY1"/Obj1
B  : "KEY2"/Obj2
C  : "KEY3"/Obj3
C  : "KEY4"/Obj4

【前提】
要求1 は、KEY2に対するエントリを更新する。
要求2 は、KEY2に対するエントリを更新する。
要求3 は、KEY2に対するエントリを更新する。
要求4 は、KEY3に対するエントリを更新する。


以下の流れを

要求1 は、KEY2に対するエントリに対して、ロックする。

要求2 は、KEY2に関するエントリに対して、ロックするがロック中のため、要求1のロック解除待ちになる。(ReentrantLock用いて)

要求3 は、KEY2に関するエントリに対して、ロックするがロック中のため、要求1のロック解除待ちになる。(ReentrantLock用いて)

要求1 は、KEY2に関するエントリに対して更新後、ロック解除する。

要求3より長く待っていた要求2がKEY2に関するエントリにロックする。

要求4 は、KEY2に関するエントリと関係ないので、ロックに影響されずに、KEY3に対するエントリに対して、ロックする。
(できる)


といった流れです。
伝わりましたでしょうか?
色々と言葉足らずで申し訳ないです。

お願いします。




評価

0

上のA,B,C,Cは、関係ないです。
すいません。無視してください。
エントリA
エントリB
エントリC
エントリD
とかで用いるつもりでしたが、説明で引用してませんでした。

評価

0

HashMapをコピーしてtableを使ってるところにひとつひとつsynchronizedを埋め込んでけばいいのでは?

評価

0

syncronizedMap(new HashMap)

でいいんじゃ?

要素に対してロック掛けるなら、
要素をクラスにすればいいだけでは?
class Youso {
  private String str1 = "KEY 4";
  public syncronized String syncLockAction() {

  }
  public void setStr1(String value) {
    str1 = value;
  }
}

評価

0

名無しさんへ
>HashMapをコピーしてtableを使ってるところにひとつひ>とつsynchronizedを埋め込んでけばいいのでは?

というのは、どういうことでしょうか?

??さんへ
要素ではなく、エントリなのですが、
KEYに対して、ロックをかけるということでしょうか?
ちょっと意図がわかりません。
申し訳ないです。

私の説明が足りないのでしょうか?

評価

0

行ロックという言葉は、データベース的ですね…

Mapに格納するオブジェクト自身のメソッドをsynchronizedにできれば、問題ないのではないでしょうか。

評価

0

>Mapに格納するオブジェクト自身のメソッドをsynchronizedにできれば、問題ないのではないでしょうか。
それ最初に私言ったことですよね。
でもすれぬし様は 順番を保障する Qweue を必要としているのですよね。
concurrrent 関連に詳しい人出ないと駄目ですね?

評価

0

KAZさんへ
そうですね、データベース的に言いますと、「レコードロック」ですかね。

割り込んだ素人さんへ
本当色々と考えて頂きありがとうございます。

なんとか出来ないか考えているのですが、自分のキャパがいけてないです。そもそもAPIで何とかしようという甘い考えが問題なんでしょうか・・・
別のアプローチとかあると嬉しいのですが・・・

評価

0

>??さんへ
>要素ではなく、エントリなのですが、
>KEYに対して、ロックをかけるということでしょうか?
>ちょっと意図がわかりません。
>申し訳ないです。

>私の説明が足りないのでしょうか?

説明が足りないのではなくて理解が足りない。

? HashMap#get("KEY4") て、KEY4 てゆーキーの
要素(エントリ)を参照するってことでしょう?

試すこともしないで反論してる?

A  : "KEY1"/Obj1
B  : "KEY2"/Obj2
C  : "KEY3"/Obj3
C  : "KEY4"/Obj4

あなたは
この Obj1〜4 が エントリだ、って言ってるのでしょう?

public class Entry {
  private String pkey;
  private String data1;
  private String data2;
 
  public Entry(String pkey, String data1, String data2) {
     //...
  }
 
  public syncronized void doUpdate1() {

  }
  public syncronized void doUpdate2() {

  }
  public syncronized void doUpdate3() {

  }

  //メンバの GETTER/SETTER


//マップ初期化
Map map = new HashMap();
map.put("KEY1", new Entry("1","d01","d02"));


//マップ参照&ロック
map.get("KEY1").doUpdate2();

評価

0

??さんへ

KEYとObjの組み合わせでエントリ(Map.Entry)という認識です。
サンプルプログラムは、あくまでもObjへのロック、排他ですよね。
エントリ自体の登録、削除時は、どう足掻いても、テーブル(Map)へのロックは必須であることに気づきました。
ありがとうございました。

その他、色々アドバイス下さった方、ありがとうございました。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。