Are concurrent programming synchronized variables thread safe

 

catalogue

Thread safety

Single thread operation variable

Multiple threads are read-only to variables or variables do not belong to shared resources

Thread unsafe condition

Multithreading can read and write variables

A subclass overrides a parent class method to perform an unknown operation

Variables: normal member variables, static member variables, and local variables

① If the variable does not belong to or is not shared by multiple threads, it is thread safe

② Variables are shared by threads; However, there are only read operations, not any write (modify) operations; Thread safe

Thread safety

Single thread operation variable

@Slf4j(topic = "c.SafeThread")
public class SafeThread {
    private List<Integer> list1 = new ArrayList(); // Common member variable
    private static List<Integer> list2 = new ArrayList(); // Static member variable
    private final int OP_NUM = 1000; // Number of operations

    private final void method(){
        List<Integer> list3 = new ArrayList(); // local variable

        for(int i = 0; i < OP_NUM; i++){
            list1.add(i); // Add an element to a normal member variable
            list2.add(i); // Add an element to a static member variable
            list3.add(i); // Add an element to a local variable
            list1.remove(0); // Remove an element from a normal member variable
            list2.remove(0); // Remove an element from a static member variable
            list3.remove(0); // Remove an element from a local variable
        }
        log.debug("Final common member variable list1 capacity {}", list1.size());
        log.debug("Final static member variable list2 capacity {}", list2.size());
        log.debug("Final local variable list3 capacity {}", list3.size());
    }

    public static void main(String[] args) {
        SafeThread st = new SafeThread();
        st.method();
    }
}

 

list1 common member variable, which is a shared resource for the current object

list2 static member variable, which is a shared resource for the current class

list3 local variable, which is a shared resource in method

However, they are only used in one thread (main thread) and are not shared by multiple threads, so they are thread safe

Multiple threads are read-only to variables or variables do not belong to shared resources

@Slf4j(topic = "c.SafeThread0")
class SafeThread0{
    private static final int THREAD_NUM = 4; // Number of threads
    private List<Integer> list1 = new ArrayList(); // Common member variable
    private static List<Integer> list2 = new ArrayList(); // Static member variable
    public SafeThread0(){
        list1.add(1); // Add element to list1
        list2.add(2); // Add element to list2
    }

    private void method(List<Integer> list3){
        log.debug("Get normal member variable list1 First element {}", list1.get(0));
        log.debug("Get static member variable list2 First element {}", list2.get(0));
        log.debug("Remove local variables list3 First element {}", list3.remove(0)); // There are write operations here, but they are thread safe
    }

    private void method0(){
        List<Integer> list3 = new ArrayList();
        list3.add(3);

        method(list3);
    }

    public static void main(String[] args) {
        SafeThread0 sf = new SafeThread0();

        for(int i = 0; i < THREAD_NUM; i++){
            new Thread(() -> {
                sf.method0();
            }, "t" + i).start();
        }
    }
}

The program ends normally

① list1 and list2 belong to shared resources for threads t0 ~ t3, but only read operations, thread safety

② When the list3 thread t0 ~ t3 calls the method, a new method will be created, which is not a shared variable and is thread safe

Thread unsafe condition

Multithreading can read and write variables

@Slf4j(topic = "c.UnsafeThread")
public class UnsafeThread {
    private final int THREAD_NUM = 10;
    private final int OP_NUM = 1000;
    private List<Integer> list = new ArrayList();

    private void add(){
        list.add(1);

    }

    private void remove(){
        list.remove(0);
    }

    private void method(){
        for(int i = 0; i < THREAD_NUM; i++){
            new Thread(() -> {
                for(int j = 0; j < OP_NUM; j++){
                    add();
                    remove();
                }
            }, "t" + i).start();
        }
    }

    public static void main(String[] args) {
        new UnsafeThread().method();
    }
}

When the number of threads is small and the number of executions is small, exceptions may not be thrown; But these are accidental. It is unsafe for multithreads to read and write variables

A subclass overrides a parent class method to perform an unknown operation

class SafeBefore{
    public void method(List<Integer> list){
        add(list);
        remove(list);
    }

    private void add(List<Integer> list){
        list.add(1);
    }

    public void remove(List<Integer> list){ // The parent class exposes internal methods
        list.remove(0);
    }
}

class UnsafeAfter0 extends SafeBefore{
    @Override
    public void remove(List<Integer> list) { // Class override parent method
        list.remove(0);
        list.remove(0);
    }
}

class Test8{
    public static void main(String[] args) {
        SafeBefore uf = new UnsafeAfter0();
        List<Integer> list = new ArrayList();
        uf.method(list);
    }
}

class UnsafeAfter1 extends SafeBefore{
    @Override
    public void remove(List<Integer> list) { // Class override parent method
        new Thread(() -> { // Directly create a new thread to turn the list into a shared resource
            list.set(1, 1);
        }, "Unsafe1").start();
    }
}

class Test8{
    public static void main(String[] args) {
        SafeBefore uf = new UnsafeAfter1();
        List<Integer> list = new ArrayList();
        uf.method(list);
    }
}

① Although there is only one thread in main, the class overrides the parent class method, which is a messy operation; Directly lead to thread insecurity

② A new thread "Unsafe1" is directly created to turn the list into a shared resource. The new thread also writes to the list

Methods in a class, involving specific implementation or thread safety issues; It's best not to expose it and decorate it with private final

Keywords: Java Concurrent Programming synchronized

Added by goleztrol on Fri, 31 Dec 2021 21:58:29 +0200