Thread synchronization

Synchronized code block

/** * Example: create three Windows to sell tickets, a total of 100 tickets. 1. Problem: There are duplicate tickets and wrong tickets in the ticket selling process --> there are thread safety problems * 2. The reason for the problem is that while one thread is operating on a ticket, while the operation is not complete, other threads join in and also operate on the ticket. * 3. How to solve the problem: When thread A operates ticket, other threads cannot participate. Until thread A finishes operating ticket, other * threads can start operating ticket. This condition cannot be changed even if thread A is blocked. * * * 4. In Java, we solve thread safety problems through synchronization mechanism. * * Mode 1: synchronized code block * * synchronized {* // The code to be synchronized * *} * Description: 1. Code that operates on shared data is code that needs to be synchronized. Can't contain too much code, can't contain too little code. * 2. Shared data: Variables operated by multiple threads. For example, ticket is shared data. * 3. Synchronization monitor, commonly known as: lock. An object of any class can act as a lock. * ** ** Requirement: Multiple threads must share the same lock. * * Sideband: In implementing the Runnable interface to create multiple threads, we can consider using this as a synchronization monitor. * Mode 2: Synchronization method. * If the code that operates on shared data is fully declared in a method, we might as well declare the method synchronized. * * * 5. The way of synchronization, to solve the problem of thread safety. -- Benefits * When manipulating synchronized code, only one thread can participate, while the other threads wait. It's a single-threaded process, which is inefficient. -- Limitations * */
class Window1 implements Runnable{

    private int ticket = 100;
// Object obj = new Object();
// Dog dog = new Dog();
    @Override
    public void run(a) {
// Object obj = new Object();
        while(true) {synchronized (this) {Synchronized (dog) {synchronized (dog) {

                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + The ticket number is: + 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("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); }}class Dog{}Copy the code

Synchronized methods

/** ** The thread safety of the Runnable interface is addressed by using synchronous methods. The synchronization method still refers to the synchronization monitor, but we don't need to declare it explicitly. * 2. Non-static synchronization method, synchronization monitor is: this * static synchronization method, synchronization monitor is: the current class itself * */


class Window3 implements Runnable {

    private int ticket = 100;

    @Override
    public void run(a) {
        while (true) { show(); }}private synchronized void show(a){// Sync monitor: this
        //synchronized (this){

            if (ticket > 0) {

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + The ticket number is: + ticket);

                ticket--;
            }
        / /}}}public class WindowTest3 {
    public static void main(String[] args) {
        Window3 w = new Window3();

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

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); }}Copy the code
/** * use synchronous methods to handle Thread safety issues in the way Thread classes are inherited ** /
class Window4 extends Thread {


    private static int ticket = 100;

    @Override
    public void run(a) {

        while (true) { show(); }}private static synchronized void show(a){// Sync monitor: window4.class
        //private synchronized void show(){// synchronized: t1, T2,t3. This solution is wrong
        if (ticket > 0) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + The ticket number is:+ ticket); ticket--; }}}public class WindowTest4 {
    public static void main(String[] args) {
        Window4 t1 = new Window4();
        Window4 t2 = new Window4();
        Window4 t3 = new Window4();


        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); }}Copy the code

Singleton – slob style

/** * rewrites lazy singleton patterns to thread-safe ** / using synchronization
public class BankTest {}class Bank{

    private Bank(a){}

    private static Bank instance = null;

    public static Bank getInstance(a){
        // Method 1: less efficient
// synchronized (Bank.class) {
// if(instance == null){
//
// instance = new Bank();
/ /}
// return instance;
/ /}
        // Method 2: Be more efficient
        if(instance == null) {synchronized (Bank.class) {
                if(instance == null){

                    instance = newBank(); }}}returninstance; }}Copy the code

Deadlock of thread

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * Note: * 1) deadlock occurs, there is no exception, there is no prompt, but all threads are blocked, cannot continue * 2) we use synchronization, to avoid deadlock. * * /
public class ThreadTest {

    public static void main(String[] args) {

        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();


        new Thread(){
            @Override
            public void run(a) {

                synchronized (s1){

                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }


                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }


                }

            }
        }.start();


        new Thread(new Runnable() {
            @Override
            public void run(a) {
                synchronized (s2){

                    s1.append("c");
                    s2.append("3");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4"); System.out.println(s1); System.out.println(s2); } } } }).start(); }}Copy the code

The lock lock

/** ** ** ** ** ** ** ** ** ** ** Interview question: The similarities and differences between synchronized and Lock? * Identical: both address thread-safety issues * Different: Synchronized releases the monitor automatically after executing the corresponding synchronization code * Lock requires a manual start of synchronization (Lock ()), and a manual end of synchronization (unlock()) * * 2. Priority order: * Lock  synchronize code blocks (already in the method body, allocated resources)  synchronize methods (outside the method body) * * * Interview questions: How to solve thread safety problems? There are several ways */
class Window implements Runnable{

    private int ticket = 100;
    1. Instantiate ReentrantLock
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run(a) {
        while(true) {try{

                //2. Call the lock method lock()
                lock.lock();

                if(ticket > 0) {try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ": Ticket number:" + ticket);
                    ticket--;
                }else{
                    break; }}finally {
                //3. Unlock ()lock.unlock(); }}}}public class LockTest {
    public static void main(String[] args) {
        Window w = new Window();

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

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); }}Copy the code

Thread communication

/** * Example of thread communication: print 1-100 using two threads. Thread 1, thread 2 alternately prints * * the three methods involved: * wait(): Once this method is executed, the current thread blocks and releases the synchronization monitor. * Notify (): Once this method is executed, one of the threads being waited is woken up. If more than one thread is waited, the one with the highest priority is awakened. * notifyAll(): Once this method is executed, it wakes up all the threads being waited. Wait (), notify(), and notifyAll() must be used in synchronized code blocks or synchronized methods. * 2. The caller of wait(), notify(), and notifyAll() must be a synchronization block or a synchronization monitor in a synchronization method. * otherwise, there will be abnormal IllegalMonitorStateException * 3. The wait (), notify () and notifyAll () three methods is defined in the Java lang. Object class. * * What are the similarities and differences between sleep() and wait()? * 1. Similarities: Once a method is executed, it can cause the current thread to block. Sleep () can be called in any scenario where it is needed. Sleep () can be called in any scenario where it is needed. Wait () must be used in synchronized blocks or methods * 3) On whether to release the synchronization monitor: If both methods are used in synchronized blocks or methods, sleep() does not release the lock, and wait() does. * * /
class Number implements Runnable{
    private int number = 1;
    private Object obj = new Object();
    @Override
    public void run(a) {

        while(true) {synchronized (obj) {

                obj.notify();

                if(number <= 100) {try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;

                    try {
                        // blocks the thread that calls wait() as follows
                        obj.wait();
                    } catch(InterruptedException e) { e.printStackTrace(); }}else{
                    break;
                }
            }

        }

    }
}


public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);

        t1.setName(Thread 1 "");
        t2.setName(Thread 2 ""); t1.start(); t2.start(); }}Copy the code