Using synchronized g keyword in Java to solve the problem of ticket overselling

This article is an original article of Joshua 317. Please indicate: reprinted from Joshua 317 blog Using synchronized g keyword in Java to solve the problem of ticket overselling - Joshua 317's blog

1, Multithreading problem

Let's first look at what happens to multi-threaded ticket selling without locking mechanism when synchronized is not used?

package com.joshua317;

public class Ticket extends Thread{
    private static int ticketNums = 100;
    public static void main(String[] args) {
        Ticket ticket1 = new Ticket();
        Ticket ticket2 = new Ticket();
        Ticket ticket3 = new Ticket();

        ticket1.start();
        ticket2.start();
        ticket3.start();
    }

    @Override
    public void run() {
        while (true) {
            if (ticketNums <=0) {
                System.out.println("Tickets have been sold out!");
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Ticket window:" + Thread.currentThread().getName() + " Sell a ticket," + "The remaining votes are:" + (--ticketNums));
        }
    }
}

In the above example, we can find that when multithreading is running, it will lead to a negative number, that is, overselling. The reason is that the threads are out of sync. Multiple threads Thread-0, Thread-1 and Thread-2 of the same process share the same storage space. They see only one ticket left at the same time, and they rob it at the same time. When a thread grabs it, other threads have passed the code of if to judge the number of votes, so when the last one is robbed, the ticket has changed to - 1 or - 2.

Next, we use the synchronized keyword by creating threads in two ways. Let's take a look at the usage of synchronized

2, Using synchronized synchronized code block to solve thread locking

2.1 create threads by inheriting threads and use synchronized

package com.joshua317;

public class Ticket extends Thread{
    private static int ticketNums = 100;
    public static void main(String[] args) {
        Ticket ticket1 = new Ticket();
        Ticket ticket2 = new Ticket();
        Ticket ticket3 = new Ticket();

        ticket1.start();
        ticket2.start();
        ticket3.start();
    }

    @Override
    public void run() {
        while (true) {
            //Method. Use synchronized. Note that the object locked by the synchronization lock is ticket class
            synchronized (Ticket.class) {
                if (ticketNums <=0) {
                    System.out.println("Tickets have been sold out!");
                    break;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Ticket window:" + Thread.currentThread().getName() + " Sell a ticket," + "The remaining votes are:" + (--ticketNums));
            }
        }
    }
}

2.2 create threads by implementing the Runnable interface and use synchronized

package com.joshua317;

public class TicketRun implements Runnable{
    private static int ticketNums = 100;
    public static void main(String[] args) {
        TicketRun ticket = new TicketRun();

        Thread thread1 = new Thread(ticket);
        Thread thread2 = new Thread(ticket);
        Thread thread3 = new Thread(ticket);

        thread1.start();
        thread2.start();
        thread3.start();
    }

    @Override
    public void run() {
        while (true) {
            //Method. Use synchronized. Note that the object locked by the synchronization lock is this
            synchronized (this) {
                if (ticketNums <=0) {
                    System.out.println("Tickets have been sold out!");
                    break;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Ticket window:" + Thread.currentThread().getName() + " Sell a ticket," + "The remaining votes are:" + (--ticketNums));
            }
        }
    }
}

3, Java synchronized keyword

In Java, synchronized code blocks are marked with the synchronized keyword. Synchronization blocks in Java are synchronized on an object. The method or code block declared by the synchronized keyword can only be accessed by one thread at a time, that is, all synchronized blocks synchronized on the same object can only be entered and executed by one thread at the same time. All other threads trying to enter the synchronization block will be blocked until the thread executing in the synchronization block exits the synchronization block.

The disadvantage is that using synchronized will affect efficiency.

3.1 code blocks using synchronized

synchronized(Obj){}

Obj is called synchronization monitor. It can be any object, but it is generally a shared resource.

There is no need to specify the synchronization monitor in the synchronization method, because the synchronization monitor of the synchronization method is the object itself or class.

[for example, there is class A, there is a synchronization method in class A, and this in the synchronization method of a is the synchronization monitor]

Synchronization monitor execution process:

The first thread accesses, locks the synchronization monitor, executes the code in {}, accesses the second thread, finds that the synchronization monitor is locked and cannot be accessed, ends the execution of the first thread, unlocks the synchronization monitor, accesses the second thread, the synchronization monitor is unlocked, and then locks and executes {} its code

Class 3.2 methods use synchronized

public synchronized void methordName(){}

Note that the synchronized keyword is used in the methordName() method declaration to tell Java that the method is synchronized.

The synchronous instance method in Java synchronizes on the instance (object) that owns the method. Therefore, the instance method of each instance object will be synchronized on different objects (the instance object itself that owns the instance method). Only one thread per instance can execute in the synchronous instance method. If there are multiple threads, for each instance object, only one thread can enter its synchronous instance method for execution at the same time. That is, one thread per instance.

This article is an original article of Joshua 317. Please indicate: reprinted from Joshua 317 blog Using synchronized g keyword in Java to solve the problem of ticket overselling - Joshua 317's blog

Keywords: Java Back-end

Added by bcamp1973 on Sat, 12 Feb 2022 06:42:47 +0200