synchronized在线程中最重要的功能还是保护线程安全,在线程处理的时候十分容易出现对数据的同时调用,这个时候出现问题主要是在面临线程处理了两次,但在这两次里面,实际上得到答案只得到了一次。
那么为了解决这样的问题,必须要在处理一个计算某个在多个线程中同时出现的问题的时候直接避免其他线程也得到这个变量或者算式。那么在java之前的版本中更多实现的Volatile。在使用的时候出现了可见性的问题。类似在现在医院里面假如已经充满了患者的情况下,救护车没有可见性的话可能依然将病人带入这个医院,但到达之后才会发现医院里面全是患者的情况,,Volatile就很好的实现了这个特点,但存在问题,Volatile的适用范围太小了
1. 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
2. 该变量没有包含在具有其他变量的不变式中。
那么我在这里列出一下volatile和synchronized之间的区别
- volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
- volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
- volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
- volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
- volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
public class AccountingSyncBad implements Runnable{
static int i=0;
public synchronized void increase(){
i++;
}
@Override
public void run() {
for(int j=0;j<1000000;j++){
increase();
}
}
public static void main(String[] args) throws InterruptedException {
//new新实例
Thread t1=new Thread(new AccountingSyncBad());
//new新实例
Thread t2=new Thread(new AccountingSyncBad());
t1.start();
t2.start();
//join含义:当前线程A等待thread线程终止之后才能从thread.join()返回
t1.join();
t2.join();
System.out.println(i);
}
}
在这种情况下就可以保证线程安全,但如果在第三行删除synchronized的话,出现的结果很难是20000,出现的更大概率是小于两万但大于或者等于10000的数字