volatile
它所修饰的变量不保留拷贝, 直接访问主内存中的.
在 Java 内存模型中, 有 main memory, 每个线程也有自己的 memory (例如寄存器). 为了性能, 一个线程会在自己的 memory 中保持要访问的变量的副本. 这样就会出现同一个变量在某个瞬间, 在一个线程的 memory 中的值可能与另外一个线程 memory 中的值, 或者 main memory 中的值不一致的情况. 一个变量声明为 volatile, 就意味着这个变量是随时会被其他线程修改的, 因此不能将它 cache 在线程 memory 中.
使用场景
您只能在有限的一些情形下使用 volatile 变量替代锁. 要使 volatile 变量提供理想的线程安全, 必须同时满足下面两个条件:
1) 对变量的写操作不依赖于当前值.
2) 该变量没有包含在具有其他变量的不变式中.
volatile 最适用一个线程写, 多个线程读的场合.
如果有多个线程并发写操作, 仍然需要使用锁或者线程安全的容器或者原子变量来代替.
synchronized
当它用来修饰一个方法或者一个代码块的时候, 能够保证在同一时刻最多只有一个线程执行该段代码.
当两个并发线程访问同一个对象 object 中的这个 synchronized(this) 同步代码块时, 一个时间内只能有一个线程得到执行. 另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块.
然而, 当一个线程访问 object 的一个 synchronized(this) 同步代码块时, 另一个线程仍然可以访问该 object 中的非 synchronized(this) 同步代码块.
尤其关键的是, 当一个线程访问 object 的一个 synchronized(this) 同步代码块时, 其他线程对 object 中所有其它 synchronized(this) 同步代码块的访问将被阻塞.
当一个线程访问 object 的一个 synchronized(this) 同步代码块时, 它就获得了这个 object 的对象锁. 结果, 其它线程对该 object 对象所有同步代码部分的访问都被暂时阻塞.
共享资源及增删改的对象.
volatile 和 synchronize 的区别
volatile 是变量修饰符, 而 synchronized 则作用于一段代码或方法.
volatile 只是在线程内存和 "主" 内存间同步某个变量的值; 而 synchronized 通过锁定和解锁某个监视器同步所有变量的值, 显然 synchronized 要比 volatile 消耗更多资源.
volatile 不会造成线程的阻塞; synchronized 可能会造成线程的阻塞.
volatile 保证数据的可见性, 但不能保证原子性; 而 synchronized 可以保证原子性, 也可以间接保证可见性, 因为它会将私有内存中和公共内存中的数据做同步.
volatile 标记的变量不会被编译器优化; synchronized 标记的变量可以被编译器优化.
线程安全包含原子性和可见性两个方面, Java 的同步机制都是围绕这两个方面来确保线程安全的.
关键字 volatile 主要使用的场合是在多个线程中可以感知实例变量被修改, 并且可以获得最新的值使用, 也就是多线程读取共享变量时可以获得最新值使用.
关键字 volatile 提示线程每次从共享内存中读取变量, 而不是私有内存中读取, 这样就保证了同步数据的可见性. 但是要注意的是: 如果修改实例变量中的数据
例如: i++, 也就是 i=i+1, 则这样的操作其实并不是一个原子操作, 也就是非线程安全的. 表达式 i++ 操作步骤分解如下:
1) 从内存中取出 i 的值.
2) 计算 i 的值;
3) 将 i 的值写到内存中.
假如在第 2 步计算值得时候, 另外一个线程也修改 i 的值, name 这个时候就会出现脏读数据. 解决的办法就是使用 synchronized 关键字. 所以说 volatile 本身并不处理数据的原子性, 而是强制对数据的读写及时的影响到主内存中.
更多 web 开发 https://www.html.cn/ 知识, 请查阅 HTML 中文网 !!
来源: http://www.css88.com/qa/other/19927.html