原子性操作:
这样一段代码。
我们输出一下:
我们发现它的结果和我们想的不太一样。
正常应该输出1000.
这是因为没有保证原子性。
所以我们来加上原子性:
这样就保证了我们的原子性。
接下来我们来细说说这个关键字:
我发现我们同时输出了这两个实例对象。
所以我们可以看出我们修饰普通方法是锁住实例对象,而不是锁住这个类。
修饰静态方法:修饰整个类
调用静态方法。
这次是第一个线程方法执行完,第一个线程睡眠结束之后才执行第二个线程中的方法。
修饰代码块:
修饰代码块锁住的也是对象实例。就是synchronized括号里的对象
volatile关键字和使用场景:
单例与线程安全:
饿汉式:
饿汉式本身就是线程安全的,所以不需要去加锁等操作。
懒汉式:
我们模拟了一个耗时场景下的懒汉式单例模式:
我们可以看到它返回的每个单例实例对象都不同,并不是我们想要的单例效果。
由此也可以看出我们的懒汉式简单写法是不符合线程安全的。
我们只需要给返回的方法加上synchronized关键字,再去运行:
就可以保证我们的线程安全了。
但是这种写法并不是一个最好的写法,因为我们在方法上加锁,当多线程的时候,其他线程不能立刻调用这个方法,所以也是比较耗时的。
我们可以换个地方加synchronized关键字并进行双重校验:
但是java中存在指令重排的情况,所以我们还要去进行一步修改才能做到最好的让懒汉式实现线程安全:
我们给类加上volatile关键字,这个关键字可以避免指令重排。
如何去避免线程安全性问题: