Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

Code shrimp is a sand carving and funny boy who likes listening to music, playing games and writing as well as most of his friends. The days are still very long, let’s refuel our efforts together 🌈

✨ role

Taking the double-checked singleton pattern as an example, start with the code

public class Singleton {

    public Singleton(a) {}private static volatile Singleton singleton;

    public static Singleton getSingleton(a) {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = newSingleton(); }}}returnsingleton; }}Copy the code

As the code above shows, The Singleton uses the volatile modifier, and we all know what volatile does

  1. Atomicity is not guaranteed
  2. Ensure visibility of shared variables
  3. Disallow instruction reordering


So what exactly does volatile do in singleton mode?

In fact, in singleton mode, volatile is primarily used to prohibit instruction reordering

So why?

In the above code, singleton = new Singleton(); It can be decomposed into the following steps:

  1. Allocates object memory space
  2. Initialize an object
  3. Set the Singleton to the allocated memory address


But step 2,3 can be swapped, that is, reordering, but according to the Java language specification intra-thread semantics, it allows reordering that does not change the execution result of a single-threaded program in a single thread. In other words, if step 2,3 is reordered, for a single thread, The first time you access an object, the result is always correct, so it doesn’t matter if you reorder it.




However, in a multi-threaded environment, this can be problematic, for example, in the following reordering case:

time Thread A Thread B
t1 Allocating object space
t2 Set singleton to point to allocated memory space
t3 Check whether the singleton is empty
t4 Since the Singleton is not NULL, thread B will access the object referenced by the Singleton
t5 Initialize an object
t6 Access the object referenced by the Singleton





In normal flow, thread A should initialize the Singleton at t2 time, and thread B at t2 time


You might have a friend who’s just about to kick in, so I’ll say it again according to the code

public class Singleton {

    public Singleton(a) {}private static volatile Singleton singleton;

    public static Singleton getSingleton(a) {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = newSingleton(); }}}returnsingleton; }}Copy the code

According to the code, if thread A is at line 12 then singleton = new Singleton(); If (singleton == null) on line 9, thread B may determine that the singleton is not null, and then take the returned singleton to do something else, resulting in an error.




At this point, I believe that you almost understand, if you do not understand, you can read it twice.

So to address this problem, we used volatile to modify the Singleton to prevent possible problems with reordering.

😉 Featured column

Self-introduction, to everyone recommend their column 😁, welcome small partners to collect attention 😊

The small white to learn Java

MybatisPlus column

App crawler Column

PC side crawler column

Big factory interview question column


❤ finally

I am aCode pipi shrimp, a prawns lover who loves to share knowledge, will update useful blog posts in the future, looking forward to your attention!!

Creation is not easy, if this blog is helpful to you, I hope you can == one key three even oh! Thank you for your support. See you next time