Java multithreaded communication security issues

Java multithreaded communication security issues

Problem Description:

In the daily production, we have all bought train tickets, and the tickets will only show that they are available and sold out. In the program, if we only open one window, there will be no problem, but in actual operation, there must be multiple windows for ticket sales, and we have to use multi-threaded methods to sell tickets. At this time, there will be a problem. We do not impose any restrictions on threads. If there is no information communication between multiple threads, there will be a negative number of votes.

The multi-threaded code is as follows

public static void main(String[] args) {
    
    
    Ticket t1 = new Ticket();
    //开设四个窗口来售票
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
}
static class Ticket implements Runnable{
    
    
    private int count = 10;
    @Override
    public void run() {
    
    
        while (count>0){
    
    
            try {
    
    
                //为了使线程更容易出问题,让线程慢一点
                Thread.sleep(1000);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println("售票中");
            count--;
            System.out.println("出票成功,还剩:"+count+"张票");
        }
    }
}

At this time there will be a problem:

Insert picture description here

We can see that even if the number of votes is 0, the thread is still selling tickets desperately.

Three ways to solve security problems

The solution is essentially to queue the program for execution and add a lock to a block of code

Synchronization code block:

The synchronized (lock object) keyword adds a lock mark to the lock object. When a thread is performing a task, lock it and let the subsequent threads wait. Once the locked thread completes the task, it will open the lock and let the thread Continue to grab. This operation continues until the end of the program.

code show as below

public static void main(String[] args) {
    
    
    Ticket t1 = new Ticket();
    //开设四个窗口来售票
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
}
static class Ticket implements Runnable{
    
    
    private int count = 10;
    //创建一个锁对象o  o只能设置一个,不然就起不到锁的效果  比如说把这行代码放入while循环里面,就变成每一个线程一把锁
    Object o = new Object();
    @Override
    public void run() {
    
    
        while (true) {
    
    
            //下面一行注释掉的代码就是给每一个线程创建一个对象,就起不到排队的效果
            //Object o = new Object();
            //给o加一个锁
            synchronized (o) {
    
    
                if (count > 0) {
    
    
                    try {
    
    
                        //为了使线程更容易出问题,让线程慢一点
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    System.out.println("售票中");
                    count--;
                    System.out.println(Thread.currentThread().getName()+"出票成功,还剩:" + count + "张票");
                }else {
    
    
                    break;
                }
                }
            }
    }
}

The results are as follows:

Insert picture description here

Synchronization method:

Synchronization method, as the name suggests, is to synchronize the method and modify the sychronized keyword on the method.

public static void main(String[] args) {
    
    
    Ticket t1 = new Ticket();
    //开设四个窗口来售票
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
}
static class Ticket implements Runnable{
    
    
    private int count = 10;
    @Override
    public void run() {
    
    
        while (true) {
    
    
            boolean flag = sale();
            if (!flag){
    
    
                break;
            }
        }
    }
    //把if语句单独抽为一个方法,加synchronizxed关键字修饰
    public synchronized boolean sale(){
    
    
        if (count > 0) {
    
    
            try {
    
    
                //为了使线程更容易出问题,让线程慢一点
                Thread.sleep(500);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println("售票中");
            count--;
            System.out.println(Thread.currentThread().getName()+"出票成功,还剩:" + count + "张票");
            return true;
        }
        return false;
    }
}

The results are as follows:

Insert picture description here

(Multiple threads here operate on the t1 object. If three objects are new, the synchronization method will not be effective)

Explicit lock:

Both synchronization code blocks and synchronization methods are implicit locks. An explicit lock is to call the lock method and control the position of the lock.

public static void main(String[] args) {
    
    
    Ticket t1 = new Ticket();
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
    new Thread(t1).start();
}

static class Ticket implements Runnable {
    
    
    private int count = 10;
    //调用Lock类
    private Lock l = new ReentrantLock();

    @Override
    public void run() {
    
    
        while (true) {
    
    
            //从代码这个位置开始锁
            l.lock();
            if (count > 0) {
    
    
                try {
    
    
                    Thread.sleep(500);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println("售票中");
                count--;
                System.out.println(Thread.currentThread().getName() + "出票成功,还剩:" + count + "张票");
            }else {
    
    
                break;
            }
            //从代码这里解锁
            l.unlock();
        }
    }
}

The results are as follows:

Insert picture description here

The difference between explicit lock and implicit lock

Implicit lock (synchronized) Explicit lock (synchronized) The specific use method to solve the security problem of multi-threaded communication has been demonstrated clearly above, so what is the difference between them?

They have the following differences:

1. Time of birth

Implicit locks existed when Java was born. They are operated at the JAM level and belong to the JAM level locks, while the explicit locks are functions that only exist after JDK5 and belong to the API level locks.

2. How to use

When using explicit and implicit, the difference is whether the user needs to manually write code to acquire and release the lock.

3. Is it fair

Implicit lock: unfair lock

Explicit lock: its fairness can be set by code, and the default is an unfair lock. In its construction method, you can pass in a Boolean value to change, true: fair lock, false: unfair lock.

4. Performance comparison

Implicit locks are operated by the JVM. Explicit locks are implemented directly through code. Before JDK1.5, the performance of implicit locks was low, but after the update of JDK1.6, Java officially modified the underlying code. Now As far as performance is concerned, there is no difference. The official also said that in the future it will support more implicit locks (synchrnoized) and optimize more things.

5. Can be interrupted

Explicit lock: Explicit lock is not interruptible unless an exception is thrown or normal operation is completed.

Implicit lock: Implicit lock can be interrupted. Interruption mode: 1. Call the set timeout method tryLock(long time, TimeUnit) time: the time to wait TimeUnit time parameter unit

After the update of JDK1.6, Java officially modified the underlying code. As far as performance is concerned, there is no difference. The official also said that it will support synchrnoized more in the future and optimize more things.

5. Can be interrupted

Explicit lock: Explicit lock is not interruptible unless an exception is thrown or normal operation is completed.

Implicit lock: Implicit lock can be interrupted. Interruption mode: 1. Call the set timeout method tryLock(long time, TimeUnit) time: the time to wait TimeUnit time parameter unit

  1. Call the interrupt() method to interrupt the operation of the program

Guess you like

Origin blog.csdn.net/weixin_46687295/article/details/106162371