[Java Multithreading] Use synchronization methods to solve thread safety problems

Description: If the code for operating shared data is completely declared in a method, we might as well synchronize this method

Take the question: Create three windows to sell tickets, and the total number of tickets is 100 as an example

One: Use the synchronization method to solve the thread safety problem of implementing the Runnable interface

According to the previous article, the method of using synchronized code blocks to solve the thread safety problem of implementing the Runnable interface code is as follows:

class Window1 implements Runnable{

    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (this){//此时的this:唯一的Window1的对象 synchronized (obj) {
                if (ticket > 0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
                    ticket--;
                }else {
                    break;
                }
            }
        }
    }
}
public class WindowTest1{
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

We will fully declare the code for manipulating shared data in a method

private synchronized void show(){
        if (ticket > 0) {
             try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
            ticket--;
        }
    }

To sort it out, the complete code is as follows:

class Window1 implements Runnable {

    private int ticket = 100;

    @Override
    public  void run() {
        while (true) {
            show();
        }
    }
    private synchronized void show(){
        if (ticket > 0) {
             try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

There is a default sync monitor "this" in the show method

Imitate the above method and apply it to use the synchronization method to deal with the thread safety problem in the method of inheriting the Thread class. In the code of inheriting the Thread class to create multiple threads, the code for operating the shared data is completely declared in a method

code show as below:

class Window extends Thread {

    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    private synchronized void show(){
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(getName() + "卖票,票号为:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest {
    public static void main(String[] args) {

        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

The running results are as follows;

We can see that there is still a wrong ticket. This is because there is a default synchronization monitor "this" in the show method  mentioned above. In this program, we have created three objects so the synchronization monitor: t1, t2 ,t3. However, multiple threads must share the same lock (synchronization monitor)

We can change the show method to be static

class Window extends Thread {

    private static int ticket = 100;

    @Override
    public void run() {
        while (true) {
            show();
        }
    }

    private static synchronized void show(){//同步监视器:t1,t2,t3
        if (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest {
    public static void main(String[] args) {

        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}

The synchronization monitor at this time is the current class -->Window.class 

==================================================== ========================== Summary:

1. The synchronization method still involves the synchronization monitor, but we don't need to explicitly declare it

2. Non-static synchronization method, the synchronization monitor is: this Static synchronization method, the synchronization monitor is: the current class itself

thanks for watching! ! !

Guess you like

Origin blog.csdn.net/qq_64976935/article/details/128891043