Doubts about synchronized of Runnable and Thread in multithreading

Posted by renegade33 on Wed, 30 Oct 2019 14:44:03 +0100

When learning java, I met a question with my classmates:

Turn from https://blog.csdn.net/qq_40857349/article/details/102809100

A company organizes the annual meeting. There are two entrances when entering the meeting. Each employee can get a double color ball lottery ticket when entering the meeting. Suppose there are 100 employees in the company, use multi-threaded simulation to enter the annual meeting.
Count the number of people entering each entrance and the number of tickets each employee gets. The print format after thread running is as follows:
Employees with No. 2 enter from the back door! The number of the two color ball lottery is: [17, 24, 29, 30, 31, 32, 07]
Employees with No. 1 enter from the back door! The number of the two color ball lottery is: [06, 11, 14, 22, 29, 32, 15]
    //.....
Total number of employees entering from the back door: 13
Staff entering from the front door: 87 employees in total

Students use the inherited Thread class to write:

public class ShuangSeQiu extends Thread{
    static int count=1;
    int []arr=new int [7];
    int countHou=0;
    int countQian=0;
    public ShuangSeQiu(String name) {
        super(name);
    }


    @Override
    public synchronized void run() {
//        synchronized (this){
            while(count<101){
                for (int i = 0; i < arr.length; i++) {
                    arr[i]=new Random().nextInt(99);
                }
                if (Thread.currentThread().getName()=="back door"){
                    countHou++;
                }else {
                    countQian++;
                }
                System.out.println("Number is"+(count++)+"Employees from"
                        +Thread.currentThread().getName()
                        +"Admission! The number of the bicolor lottery is:"+ Arrays.toString(arr));
            }
        if (Thread.currentThread().getName()=="back door"){
            System.out.println("The total number of employees entering through the back door:"+countHou+"Position employee");        }
        else {
            System.out.println("The total number of employees entering from the front door:"+countQian+"Position employee");
        }

//        }

    }

}
//Test class

    private static void exe2() {
        ShuangSeQiu houMen=new ShuangSeQiu("back door");
        ShuangSeQiu qianMen=new ShuangSeQiu("Front door");
        houMen.start();
        qianMen.start();
    }

I use the Runnable interface to write:

public class Lottery implements Runnable {
    List<Integer> list = new ArrayList<>();
    Object lock = new Object();
    int total=1;int frontCount=0;int backCount=0;

    @Override
    public void run() {
        while(total<100){
            synchronized (lock){
            for(int i=0;i<6;i++){
                list.add(new Random().nextInt(100));
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(Thread.currentThread().getName()=="Front door"){
                frontCount++;
            }else {
                backCount++;
            }
            System.out.println("Number is:"+(total++)+"Employees from"+Thread.currentThread().getName()+"Admission! The number of the bicolor lottery is:"+list);
            list.clear();
        }
        }
        if(Thread.currentThread().getName()=="Front door"){
            System.out.println("The total number of employees entering from the front door:"+frontCount+"Position employee");
        }else {
            System.out.println("The total number of employees entering through the back door:"+backCount+"Position employee");
        }
    }
}
//Test class
public class Test {
    public static void main(String[] args) {
        Lottery lot=new Lottery();
        Thread Entry1 = new Thread(lot,"Front door");
        Thread Entry2 = new Thread(lot,"back door");
        Entry1.start();
        Entry2.start();

    }
}

If you use Runnbale to implement, the program will run as expected when you put synchronized in the while, but if you put synchronized in the run, you will go through all the front doors or all the back doors.

After discussing with the students, we came to the following conclusions:

When the interface is used for implementation, it operates on the same Lottery() object, so the two threads are running concurrently. Therefore, when using synchronized on run, the thread that executes first will be locked, and it will not enter the next thread until it finishes executing, so there will be a full pass front door or full pass back door.

When using inheritance class to implement, two objects are operated, so two threads are carried out in parallel. Because the number of employees count is a static static variable, there is only one, so there will be no duplicate employees, but sometimes there will be 101 people (the title is 100 people), because when one thread is 99, two threads run again at the same time, two threads. After count + +, it becomes 101 people.

Topics: Java