java Synchronized Volatile

参考链接:

http://tutorials.jenkov.com/java-concurrency/synchronized.html

http://tutorials.jenkov.com/java-concurrency/volatile.html

https://blog.csdn.net/jdbdh/article/details/81839225

https://blog.csdn.net/jdbdh/article/details/81774240

https://blog.csdn.net/jdbdh/article/details/81780764

学习小结

1、Synchronized

Synchronized用来声明同步块,一般的形式如下:

synchronized(object){
        ...
    }

同步代码块由两部分组成:一个为锁的对象引用(上述代码的object)和一个由这个锁保护的代码块(大括号内的代码)。将进入该代码块的线程会尝试获取锁,如果改对象没有被加锁,则该线程便获得锁并执行同步块,而其他线程尝试对对象加锁的线程都会被阻塞。不管是不是进入同一代码块,只要锁对象相同且被加锁,其他线程就必须等待。

同步块也有其他方便的写法,就是直接将synchronized直接声明在方法上,那么锁对象为拥有该方法的对象,代码块为整个方法的代码块。比如声明在对象方法上时,锁为该对象。如果声明在静态方法上,那么该方法属于类的,而类也是一个对象(类Class的对象),因此锁为该类。

2、Volatile

一般cpu从内存读时,会先将一块数据读入到cpu缓存中,然后读入缓存。写数据时,cpu会写入到cpu缓存,而缓存何时被写入到主存是不清楚的。而volatile则强制cpu每次访问volatile变量时都直接从内存中访问,而写入数据时,直接写入到主存中。

3、可见性

volatile保证了可见性很容易理解,因为不同线程被强制对内存操作了,而不是对缓存操作,就不会出现不同地方数据不一致的问题,共享数据只有一份,因此保证了不同线程对同一共享变量的可见性。

那Synchronized是如果做到的呢?因为同步块一次只有一个线程执行,因此可以规定:同步块开始执行时,将共享变量从内存中读入到cpu缓存,之后的操作可以在缓存中进行,同步块结束时将数据写回到内存中。这样下一个线程从内存中读入的数据永远是最新的,保证了数据的一致性。因此保证了不同线程对同一共享变量的可见性。

4、原子性

只有同步块才能保证原子性,volatile不能保证。所谓原子性就是同步块的代码同一时刻只能由同一个线程执行。这个和数据库事务处理的原子性不同,事务处理的原子性是指多条sql语句要么全部执行完,要么全部不执行。事务处理的原子性还是会存在并发问题,导致脏读等问题。

猜你喜欢

转载自blog.csdn.net/jdbdh/article/details/81842891