前言
看到final,我们知道final是修饰变量、类和方法的,其变量不可修改、类不能被继承、方法不能被覆盖。这是final我们知道的知识点,但是它就一定能保证原子性么?答案是否定的。
Final修饰的引用代码
package com.example.auth.config;
public class FinalExample {
//引用变量
final int[] ints ;
static FinalExample object;
public FinalExample() {
ints =new int[1];
ints[0]=1;
}
public static void writer(){
object = new FinalExample();
int temp1 =object.ints[0];
System.out.println("ints数组第一次写的值为:"+temp1);
}
public static void writerTwo(){
object.ints[0]=2;
int temp2 =object.ints[0];
System.out.println("ints数组第二次写的值为:"+temp2);
}
public static void reader(){
if (object!=null){
int temp3 =object.ints[0];
System.out.println("ints数组第一个值为:"+temp3);
}
}
public static void main(String[] args) {
Writer writer = new Writer();
WriterTwo writerTwo =new WriterTwo();
Reader reader =new Reader();
new Thread(writer,"线程A").start();
new Thread(writerTwo,"线程B").start();
new Thread(reader,"线程C").start();
}
static class Writer implements Runnable{
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"执行第一次写的操作");
writer();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class WriterTwo implements Runnable{
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"执行第二次写的操作");
writerTwo();
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Reader implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行读数据操作");
reader();
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这里创建3个线程A、B、C,线程A、B分别对ints引用变量进行2次赋值,线程C对复制的变量进行读。
让我们看看运行的结果,可以看出经过final修饰的引用变量的值被修改了。
总结
Final修饰的变量可以在声明的时候或者在构造的时候赋值,且只能在这两个地方赋值,赋值后再不能进行改变,但是对于final修饰的引用,只是引用不能再指向其他对象,但其所指对象的属性还是可以被修改的,final只有可见性。