This is the sixth day of my participation in Gwen Challenge

Concurrent Programming in Java – Basic concepts of Java multithreading

Concurrent programming in Java – sharing between threads

1. Thread insecurity caused by incorrect locking

In the last article, we wrote about the thread safety problems in Java thread sharing, and also analyzed how to solve the problem of thread safety, introduced the use of object lock synchronized, but the wrong way to use, even if you use synchronized, it is not safe



    private static class Worker implements Runnable{

        private Integer i;

        public Worker(Integer i) {
            this.i=i;
        }

        @Override
        public void run(a) {
            synchronized (i) {
                i++;
                try {
                    Thread.sleep(3000);
                } catch(InterruptedException e) { e.printStackTrace(); }}}}public static void main(String[] args) throws InterruptedException {
        Worker worker=new Worker(1);
        for(int i=0; i<5; i++) {newThread(worker).start(); }}Copy the code

In the above code we use the object lock, but we run it a few times and find that the result is not as we expected. The thread is not safe. Why? Let’s see what happens to this class after it’s compiled, okay

See, when it’s ++, it’s using the Integer valueOf method, nice, let’s take a look at the valueOf method

Look at this method and combine it with what we learned in the last article, okay? This means that every time an Integer++ in the Worker returns a new Integer, the lock object is constantly changing, so the thread is likely to be unsafe when the lock changes

2, volatile

Volatile. The lightest synchronization mechanism, volatile, guarantees visibility of operations, but not synchronization. If we do not use volatile, the variables of the objects we operate on between threads are invisible

private  static boolean ready;
    private static int number;

    private static class PrintThread extends Thread{
        @Override
        public void run(a) {
            System.out.println("PrintThread is running.......");
            while(! ready); System.out.println("number = "+number); }}public static void main(String[] args) {
        new PrintThread().start();
        SleepTools.second(1);
        number = 51;
        ready = true;
        SleepTools.second(5);
        System.out.println("main is ended!");
    }
Copy the code

As a result of executing the code above, the child thread started and changed the values of ready and number in the main thread. The child thread did not stop running and did not receive the value of number. That is the invisibility of the operation

private  static volatile boolean ready;
    private static volatile int number;
Copy the code

Our main thread operates on number and the ready child thread is visible, which ends the child thread’s execution by printing out the number

3, summarize

Synchronized is used to synchronize blocks of code, but is useless if used incorrectly. Volatile is the lightest synchronization mechanism, but it only ensures visibility, not synchronization. Synchronized is used to achieve synchronization. If there is something wrong, please point it out in the comment area, I will correct it in the first time, I hope you can connect three keys!