簡體   English   中英

同步讀取並行,一次寫入一個

[英]synchronization of read parallel , write one at a time

我有一個對象obj,它經常被許多線程讀取,但是僅由一個線程定期更新。更新發生在很長一段時間(例如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. 我不希望只有一個線程讀取數據。讀取應該是並行的。

  2. 我該如何同步讀寫?如果寫線程正在更新,而讀線程正在讀取,我沒有什么異常。如果讀到了一些舊數據就可以了3)如果寫線程正在更新時讀線程正在讀取,我會得到例外?會有什么問題嗎?

在這種情況下,您不需要任何同步。 您所要做的只是以下幾點:

  • 確保MyObject不可變的 ,這意味着您永遠不要更改對象中的任何值,而是每次更改它時都構造一個新的MyData對象。 這樣可以防止任何人看到被改變的物體。
  • 將obj聲明為volatile ,以確保所有線程每次都能看到更新后的值。

如果遵循這些步驟,您將永遠不會因為並發讀寫而獲得異常。

  1. 使用volatile關鍵字,它不會像同步一樣獲得鎖定,並且將提供多路訪問,從而將一個線程的更新反映到另一個線程。

  2. 但是最好總是進行某種同步,因為volatile不能確保防止數據出現競爭狀況。 因此,如果您不想使用同步,那么最好使用不可變對象

例如:

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());
  }


}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM