Proper use of volatile variables and synchronized blocks

I am trying to wrap my head in thread safety in java (or in general). I have this class (which, I hope, matches the POJO definition), which should also be compatible with JPA providers:

    public class SomeClass {

        private Object timestampLock = new Object();
        // are "volatile"s necessary?
        private volatile java.sql.Timestamp timestamp;
        private volatile String timestampTimeZoneName;

        private volatile BigDecimal someValue;

        public ZonedDateTime getTimestamp() {
            // is synchronisation necessary here? is this the correct usage?
            synchronized (timestampLock) {
                return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of(timestampTimeZoneName));
            }
        }

        public void setTimestamp(ZonedDateTime dateTime) {
            // is this the correct usage?
            synchronized (timestampLock) {
                this.timestamp = java.sql.Timestamp.from(dateTime.toInstant());
                this.timestampTimeZoneName = dateTime.getZone().getId();
            }
        }

        // is synchronisation required?
        public BigDecimal getSomeValue() {
            return someValue;
        }

        // is synchronisation required?
        public void setSomeValue(BigDecimal val) {
            someValue = val;
        }
    }

As indicated in the comment lines in the code, it is necessary to determine whether timestamp, and timestampTimeZoneNamehow volatile, and whether to use the tags synchronizedas they should be? Or should I only use the blocks synchronizedand not to determine timestamp, and timestampTimeZoneNamehow volatile? A timestampTimeZoneNamea timestampmust not mistakenly coincide with another timestamp.

This link says

Reading and writing are atomic for all variables declared volatile (including long and double variables)

, someValue setter/getter volatile? , ( , "" ), ?

+4
3

, , , , .

, , , getTimestamp() .

, , java.sql.Timestamp.from(dateTime.toInstant());, , , inbetween dateTime.toInstant() from. , .

synchronized (timestampLock) {
    this.timestamp = java.sql.Timestamp.from(dateTime.toInstant());
    //CONTEXT SWITCH HERE
    this.timestampTimeZoneName = dateTime.getZone().getId();
}

synchronized (timestampLock) {
    return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of(timestampTimeZoneName));
}

, , . , .

. , , . volatile, VM . , , , : " ".


someValue: , . , , , ​​ . . JIT , . .

, . , . , , . java http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html

+1

, - @Cruncher :

synchronized, , . , , , . , , .

, append (x, y), ? . , , , . .

, append (x, y). . append (x, y) x x, , . , (x, y), . , , .

, append (x, y) synchronized ( ) , synchronized . synchronized , .

, A append (x, y) B " ", B , , A ? . , , , . , , - .

, , , , . , . " " - , , .

, !

+1
    // is synchronisation required?
    public BigDecimal getSomeValue() {
        return someValue;
    }

    // is synchronisation required?
    public void setSomeValue(BigDecimal val) {
        someValue = val;
    }

, , , , getter, , , syncronization. , , .

0

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


All Articles