Writing an atom in two variables when the condition is met

I have the following class that will be used by multiple threads:

public class Container

    private volatile Date date;
    private int amount;
    private final Object lock = new Object();

    public void update(int amount){
        int actualAmount;
        if(check(date)){
              //do some BULK computation to compute the actualAmount
             synchronized(lock){
                 date = new Date();
                 this.amount = actualAmount;
             }
        }
    }

    private boolean check(Date date){
        synchronized(lock){
          //reading from the date and returning true if the date is expired
        }
    }
}

But I'm not sure of the correctness. First, I declared the field Datehow to volatileobserve changes when performing a condition check. But it may happen that when performing mass calculations, the second thread tried to perform an update that caused data races.

I do not want to put the calculation BULKin a synchronized block, because it involves calling several foreign methods and prevents JVM optimization.

Performing mass calculations twice does not harm data rows, but spends processor time.

How can I handle this in a more efficient way?

+4
2

, , , ( ), ?

    public void update(int amount) {
    int actualAmount;
    if (check(date)){
          //do some BULK computation to compute the actualAmount
         synchronized(lock) {
            if (check(date)) {
                 date = new Date();
                 this.amount = actualAmount;
            } else {
                update(amount);
            }
         }
    }
}

, , ?

, (), - , ( ).

amout? ? .

1. , . , update() .

+1

- :

public class Container

    private Date date;
    private int amount;
    private final Object lock = new Object();

    public void update(int amount){
        int actualAmount;
        Date oldDate;
        // Loop until no one call update() during our computations
        for(oldDate = checkDate(); oldDate != null; oldDate = checkDate()){
            //do some BULK computation to compute the actualAmount
            synchronized(lock){
                if(date == oldDate){
                    // No one update data inbetween
                    date = new Date();
                    this.amount = actualAmount;
                    break;
                }
            }
        }
    }

    /* Return this.date if it is expired or null otherwise */
    private Date checkDate(void){
        synchronized(lock){
          // Check .date and return appropriate value
        }
    }
}

.date, . , , - BULK-. , .

lock checkDate(), .date . , , , ( ) .

, , update() , , BULK, - : , .

+1

Source: https://habr.com/ru/post/1615705/


All Articles