1

多くのスレッドによって頻繁に読み取られるオブジェクトobjがありますが、定期的に1つのスレッドによってのみ更新されます。更新は長い間隔(たとえば10分)後に発生します。

データはあまり国境を越えていません。つまり、読み取りスレッドがしばらくの間古いデータ(古い)を取得した場合、それは完全に問題ありません。

今、私は同期のために次のアプローチを使用することを考えました:

final Object lock = new Object();
private MyObject obj = new MyObject(); //this is the data

public String getDataFieldName(){
 synchronized(lock){
   return this.obj.name;
 }
}


/*the following code is wrong right?As its just synchronizes the code for getting reference.But after getting reference read thread R1 may try to get data while write Thread is modifying data.Will that give exception?How to solve this? */
public String getData(){
 synchronized(lock){
   return this.obj;
 }
}

//only one thread can update.But how multipe threads can read at once?
public updateData(args ) {
  synchronized(lock){
    //do update
 }

}

私の質問は次のとおりです。

  1. 1つのスレッドだけがデータを読み取る必要はありません。読み取りは並列である必要があります。

  2. 読み取りと書き込みを同期するにはどうすればよいですか?書き込みスレッドが更新中であり、読み取りスレッドが読み取り中の場合、例外を取得する必要はありません。読み取りが古いデータを取得する場合は問題ありません。3)書き込みスレッドの更新中に読み取りスレッドが読み取り中の場合、例外が発生しますか?問題はありますか?

4

2 に答える 2

1

このシナリオでは、同期は必要ありません。あなたがしなければならないのは次のとおりです。

  • 不変MyObjectであることを確認してください。つまり、オブジェクトの値を変更することはありません。代わりに、オブジェクトを変更するたびに新しいオブジェクトを作成します。これにより、半分変更されたオブジェクトが誰にも表示されなくなります。MyData
  • objをvolatileとして宣言し、すべてのスレッドが毎回更新された値を参照できるようにします。

これらの手順に従うと、読み取りと書き込みが同時に行われるため、例外が発生することはありません。

于 2012-07-04T05:27:48.620 に答える
0
  1. volatileキーワードを使用します。これは、同期とは異なり、ロックを取得せず、あるスレッドから別のスレッドへの更新を反映して、複数のアクセスを提供します。

  2. ただし、揮発性ではデータの競合状態を防ぐことができないため、何らかの同期を行うことをお勧めします。したがって、同期を使用したくない場合は、Immutableオブジェクトを使用することをお勧めします

例えば:

import java.util.Date;

/**
* Planet is an immutable class, since there is no way to change
* its state after construction.
*/
public final class Planet {


 //Final primitive data is always immutable.

  private final double fMass;

  private final String fName;

  private final Date fDateOfDiscovery;

  public Planet (double aMass, String aName, Date aDateOfDiscovery) {
     fMass = aMass;
     fName = aName;
     //make a private copy of aDateOfDiscovery
     //this is the only way to keep the fDateOfDiscovery
     //field private, and shields this class from any changes that 
     //the caller may make to the original aDateOfDiscovery object
     fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
  }


  public double getMass() {
    return fMass;
  }


  public String getName() {
    return fName;
  }




  public Date getDateOfDiscovery() {
    return new Date(fDateOfDiscovery.getTime());
  }


}
于 2012-07-04T06:15:03.807 に答える