标签:vol 线程安全 java关键字 ref 同步问题 并发 volatil lse 就是
synchronized是Java语法中的一个内置锁的实现。synchronized关键字解决了代码块或者方法上的同步问题,同一时间,只有一个线程能够通过并执行。保证线程安全:内存可见性和原子性提供了并发场景的一个共享资源访问的解决方案。
当我们说synchronized锁住的是一个JVM对象时,真正发挥作用的是对象头上所指向的monitor对象(监视器机制:Java锁的底层实现)。
synchronized有两种作用域:方法或代码块
1.作用域为方法:这种作用域下,锁住的对象为this,也就是当前对象;如果方法是静态的,锁住的是当前的Class类对象。
public synchronized void synchronizeMethod() {
// do sth
}
2.作用域为代码块:锁住的对象为synchronized之后指定的对象,下例中即为resource。
public static void main() {
synchronized(resource) {
// do sth
}
}
在真正执行的时候,两者都是会去获取底层monitor锁(监视器锁)执行。
volatile只能够用于修饰变量。
它能够保证的是,变量在程序执行过程中的可见性和有序性,它不能保证变量的原子性。
1、可见性,但不保证原子性:
第一,被volatile修饰的变量,一旦有修改,会立即刷新到主内存里面。
第二,被volatile修饰的变量,一旦被一个线程修改了,其他线程马上就能够读到这个变量修改后的值(即与主内存同步)。
它不能保证变量的原子性。它只是保障了变量在读/写操作的时候,具有原子性,但是无法保证变量在任何操作的时候是原子的。例如,在多线程的场景下,一旦有多个线程同时来执行i++,即使是使用volatile修饰的变量i,也是无法保证i++执行的正确性,因为涉及到读+写。
2、有序性:
关键在于多个内存读写操作有没有被CPU硬件以及编译器软件调换顺序。
以如下代码段为例,
//线程A
1. succ=false
2. i=10
3. doSomething()
4. i=20
5. succ = true
// 线程B
6. if (succ) {
7. doSomethingB();
8. }
若succ未用volatile修饰,则可能的执行顺序为15234,succ提前置为true可能会造成线程B出现问题。
若succ使用volatile修饰,就会严格按照步骤1,中间步骤2~4,步骤5,来执行,这里面的中间步骤2~4顺序究竟如何,不用去管,但是它一定会等到中间步骤都执行完毕才去执行最后一个步骤。这就是volatile所保证的有序性。
https://bbs.byr.cn/#!article/Java/63393
[Java并发编程之美]第2章 并发编程的其他基础知识 补充知识
标签:vol 线程安全 java关键字 ref 同步问题 并发 volatil lse 就是
原文地址:https://www.cnblogs.com/coding-gaga/p/12404148.html