Problem Learning and Summary of Multi-threaded Resource Sharing

Links to the original text: https://my.oschina.net/u/580135/blog/612212

We know that there are two ways to implement traditional multithreading in Java: inheriting the Thread class or implementing Runnable. The start() method is called when the thread starts.

Implementing the Runnable interface has the following advantages over inheriting the Thread class:

1. Avoiding the limitation of single inheritance, a class can implement multiple interfaces at the same time.

2. Suitable for resource sharing.

 

The realization of multi-threaded simulation of ticket sales shows that the realization of Runnable can achieve the purpose of resource sharing.

Implementation of multi-threaded ticketing using inherited Thread class

package org.dennist.thread.demo;
/** * * TicketThread.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:22:49 * * TODO: class TicketThread. Java is used for...* */
public class TicketThreadT extends Thread{
    
    private int num = 5;        //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            if(this.num>0){        //Print ticket information
                System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
            }
        }
    }
    
    public static void main(String[] args) {
        TicketThreadT th1 = new TicketThreadT();        //Thread one
        th1.setName("Ticket booth 1");    
        TicketThreadT th2 = new TicketThreadT();        //Thread two
        th2.setName("Ticket outlet two");
        TicketThreadT th3 = new TicketThreadT();        //Line 3
        th3.setName("Ticket outlet three");
        
        //Start three threads separately
        th1.start();
        th2.start();
        th3.start();
    }
}

The results of program operation are as follows:

A total of 5 tickets, started three threads, from the print results can be seen that a total of 15 tickets were sold, there is no sharing of resources between threads.

Implementing ticket thread of Runnable

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            if(this.num>0){            //Print ticket information
                System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
            }
        }
    }

    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        Thread th1 = new Thread(ticketThread);    //Thread one
        th1.setName("Ticket booth 1");
        Thread th2 = new Thread(ticketThread);    //Thread two
        th2.setName("Ticket outlet two");
        Thread th3 = new Thread(ticketThread);    //Line 3
        th3.setName("Ticket outlet three");
        
        th1.start();
        th2.start();
        th3.start();
    }
}

Running result of program

Although there are three threads in the program now, the three threads have sold five tickets in total, that is to say, multi-threading implemented by Runnable can achieve the purpose of resource sharing.

Java Multithread Access Sharing

(1) If each thread executes the same code, the same Runnable object can be used, which share data in the Runnable object, for example, the ticketing system can do so.

(2) If the code executed by each thread is different, then different Runnable objects are needed. There are two ways to share data among these Runnable objects:

1. Encapsulate the shared data in another object and pass it one by one to each Runnable object. Each thread also assigns the operation method of sharing data to that object to complete, so it is easy to achieve mutual exclusion and communication for each operation of the data.

2. Take these Runnable objects as internal classes in a class, share data as member variables in this external class, and the operation methods of each thread to share data are also allocated to external classes, so as to realize mutual exclusion and communication of each operation to share data, and to tune each Runnable object of the internal class. Use these methods of external classes.

3. Combination of the above two ways: encapsulating the shared data in another object, and assigning the method of operation of each thread to the object, the object is a member variable or a local variable in the method of the external class, and the Runable object of each thread is a local variable in the external class. Members of internal or local internal classes.

4. In a word, the best way to synchronize mutually exclusive pieces of code is to place them in several separate methods, which are then placed in the same class, so that it is easier to achieve synchronous mutually exclusive and communication between them.

(3) The extreme and simple way is to define a static variable in any class, which will be shared by all threads.

 

 

There are several ways to set and get names in the Thread class.

Set name: public final void setName(String name)

public Thread(Runnable target, String name)

public Thread(String name)

Get the name: public final String getName()

Because of the uncertainties in the operation of a thread, a method is provided to obtain the current thread of operation.

public static Thread currentThread()

Explain:

For threads, the name is usually set before startup. It's better not to set the same name, and it's better not to change the name of a thread.

In Java execution, a Java program starts at least two threads: a main thread and a garbage collection thread.

 

Synchronization of multithreading

Is it really okay to implement the Runnable program above? We know that there are always waiting and delays in buying tickets in real life, so let's simulate buying tickets in real life and then look at the program output above.

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            try {
                Thread.sleep(200);    //Rest 200 milliseconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }        
            if(this.num>0){            //Print ticket information
                System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
            }
        }
    }

    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        Thread th1 = new Thread(ticketThread);    //Thread one
        th1.setName("Ticket booth 1");
        Thread th2 = new Thread(ticketThread);    //Thread two
        th2.setName("Ticket outlet two");
        Thread th3 = new Thread(ticketThread);    //Line 3
        th3.setName("Ticket outlet three");
        
        th1.start();
        th2.start();
        th3.start();
    }
}

If we want to solve this problem, we must use synchronization. Synchronization means that only one thread can perform multiple operations in the same period of time, and other threads can continue to execute after this thread has completed.

There are two ways to achieve synchronization:

JAVA multithreaded synchronization mainly depends on several methods and keywords
1. wait method

2. notify method and notify All method

3. synchronized keywords

4 atomic action

See:[ http://www.cnblogs.com/dennisit/archive/2013/02/25/2931573.html]

Synchronized keywords are used to solve the above problems. There are two ways to use synchronized keywords.

1. Synchronized code block

2. Synchronization method

Synchronized code block

Synchronized keywords are used to declare synchronized code blocks, but when using this operation, it is necessary to clearly indicate which object to lock, usually the current object.

Synchronized {*// is generally about this locking

// Locking objects

     }

The above problem is solved using synchronous code blocks

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            //Using Synchronized Code Blocks
            synchronized (this) {
                try {
                    Thread.sleep(300);    //Rest 300 milliseconds
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }        
                if(this.num>0){    
                    //Print ticket information
                    System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
                }
            }
            
        }
    }

    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        new Thread(ticketThread,"Ticket booth 1").start();    //Thread one
        new Thread(ticketThread,"Ticket outlet two").start();    //Thread two
        new Thread(ticketThread,"Ticket outlet three").start();    //Line 3
    }
}

 

Synchronization method

Synchronization method is to add synchronized keyword modification to the method
The above problem is solved using synchronous code blocks

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            sale();                    //Call the synchronization method
        }
    }
    
    //Using synchronization method
    public synchronized void sale(){
        try {
            Thread.sleep(300);    //Rest 300 milliseconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }        
        if(this.num>0){    
            //Print ticket information
            System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
        }
    }
    
    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        new Thread(ticketThread,"Ticket booth 1").start();    //Thread one
        new Thread(ticketThread,"Ticket outlet two").start();    //Thread one
        new Thread(ticketThread,"Ticket outlet three").start();    //Thread one
    }
}

 

Synchronization is required when multiple threads share the same resource, but too much synchronization can cause deadlock.

 

What is deadlock? What are the main causes of deadlocks? Necessary conditions for deadlock generation, how to solve deadlock?

Deadlock refers to the resource that each process in a group of processes waits indefinitely for another process in the restructured process to occupy and never release. This phenomenon is called system deadlock.

There are two main causes of deadlock:

1. Competitive resources, the limited number of resources provided by the system, can not meet the requirements of each process.

2. When multiprogramming runs, the sequence of process advancement is unreasonable.

Necessary conditions for deadlock generation

1. Mutual exclusive use of resources

2. Occupy and wait for resources

3. Do not seize resources.

4. Cyclic waiting for resources

Deadlock Solution

1. Preventing deadlocks: Breaking the conditions under which deadlocks occur (except for mutually exclusive conditions, which are unrealistic)

2. Avoid deadlocks

3. Detection and exclusion

4. Ignore it.

Problem Learning and Summary of Multi-threaded Resource Sharing

We know that there are two ways to implement traditional multithreading in Java: inheriting the Thread class or implementing Runnable. The start() method is called when the thread starts.

Implementing the Runnable interface has the following advantages over inheriting the Thread class:

1. Avoiding the limitation of single inheritance, a class can implement multiple interfaces at the same time.

2. Suitable for resource sharing.

 

The realization of multi-threaded simulation of ticket sales shows that the realization of Runnable can achieve the purpose of resource sharing.

Implementation of multi-threaded ticketing using inherited Thread class

package org.dennist.thread.demo;
/** * * TicketThread.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:22:49 * * TODO: class TicketThread. Java is used for...* */
public class TicketThreadT extends Thread{
    
    private int num = 5;        //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            if(this.num>0){        //Print ticket information
                System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
            }
        }
    }
    
    public static void main(String[] args) {
        TicketThreadT th1 = new TicketThreadT();        //Thread one
        th1.setName("Ticket booth 1");    
        TicketThreadT th2 = new TicketThreadT();        //Thread two
        th2.setName("Ticket outlet two");
        TicketThreadT th3 = new TicketThreadT();        //Line 3
        th3.setName("Ticket outlet three");
        
        //Start three threads separately
        th1.start();
        th2.start();
        th3.start();
    }
}

The results of program operation are as follows:

A total of 5 tickets, started three threads, from the print results can be seen that a total of 15 tickets were sold, there is no sharing of resources between threads.

Implementing ticket thread of Runnable

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            if(this.num>0){            //Print ticket information
                System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
            }
        }
    }

    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        Thread th1 = new Thread(ticketThread);    //Thread one
        th1.setName("Ticket booth 1");
        Thread th2 = new Thread(ticketThread);    //Thread two
        th2.setName("Ticket outlet two");
        Thread th3 = new Thread(ticketThread);    //Line 3
        th3.setName("Ticket outlet three");
        
        th1.start();
        th2.start();
        th3.start();
    }
}

Running result of program

Although there are three threads in the program now, the three threads have sold five tickets in total, that is to say, multi-threading implemented by Runnable can achieve the purpose of resource sharing.

Java Multithread Access Sharing

(1) If each thread executes the same code, the same Runnable object can be used, which share data in the Runnable object, for example, the ticketing system can do so.

(2) If the code executed by each thread is different, then different Runnable objects are needed. There are two ways to share data among these Runnable objects:

1. Encapsulate the shared data in another object and pass it one by one to each Runnable object. Each thread also assigns the operation method of sharing data to that object to complete, so it is easy to achieve mutual exclusion and communication for each operation of the data.

2. Take these Runnable objects as internal classes in a class, share data as member variables in this external class, and the operation methods of each thread to share data are also allocated to external classes, so as to realize mutual exclusion and communication of each operation to share data, and to tune each Runnable object of the internal class. Use these methods of external classes.

3. Combination of the above two ways: encapsulating the shared data in another object, and assigning the method of operation of each thread to the object, the object is a member variable or a local variable in the method of the external class, and the Runable object of each thread is a local variable in the external class. Members of internal or local internal classes.

4. In a word, the best way to synchronize mutually exclusive pieces of code is to place them in several separate methods, which are then placed in the same class, so that it is easier to achieve synchronous mutually exclusive and communication between them.

(3) The extreme and simple way is to define a static variable in any class, which will be shared by all threads.

 

 

There are several ways to set and get names in the Thread class.

Set name: public final void setName(String name)

public Thread(Runnable target, String name)

public Thread(String name)

Get the name: public final String getName()

Because of the uncertainties in the operation of a thread, a method is provided to obtain the current thread of operation.

public static Thread currentThread()

Explain:

For threads, the name is usually set before startup. It's better not to set the same name, and it's better not to change the name of a thread.

In Java execution, a Java program starts at least two threads: a main thread and a garbage collection thread.

 

Synchronization of multithreading

Is it really okay to implement the Runnable program above? We know that there are always waiting and delays in buying tickets in real life, so let's simulate buying tickets in real life and then look at the program output above.

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            try {
                Thread.sleep(200);    //Rest 200 milliseconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }        
            if(this.num>0){            //Print ticket information
                System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
            }
        }
    }

    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        Thread th1 = new Thread(ticketThread);    //Thread one
        th1.setName("Ticket booth 1");
        Thread th2 = new Thread(ticketThread);    //Thread two
        th2.setName("Ticket outlet two");
        Thread th3 = new Thread(ticketThread);    //Line 3
        th3.setName("Ticket outlet three");
        
        th1.start();
        th2.start();
        th3.start();
    }
}

If we want to solve this problem, we must use synchronization. Synchronization means that only one thread can perform multiple operations in the same period of time, and other threads can continue to execute after this thread has completed.

There are two ways to achieve synchronization:

JAVA multithreaded synchronization mainly depends on several methods and keywords
1. wait method

2. notify method and notify All method

3. synchronized keywords

4 atomic action

See:[ http://www.cnblogs.com/dennisit/archive/2013/02/25/2931573.html]

Synchronized keywords are used to solve the above problems. There are two ways to use synchronized keywords.

1. Synchronized code block

2. Synchronization method

Synchronized code block

Synchronized keywords are used to declare synchronized code blocks, but when using this operation, it is necessary to clearly indicate which object to lock, usually the current object.

Synchronized {*// is generally about this locking

// Locking objects

     }

The above problem is solved using synchronous code blocks

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            //Using Synchronized Code Blocks
            synchronized (this) {
                try {
                    Thread.sleep(300);    //Rest 300 milliseconds
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }        
                if(this.num>0){    
                    //Print ticket information
                    System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
                }
            }
            
        }
    }

    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        new Thread(ticketThread,"Ticket booth 1").start();    //Thread one
        new Thread(ticketThread,"Ticket outlet two").start();    //Thread two
        new Thread(ticketThread,"Ticket outlet three").start();    //Line 3
    }
}

 

Synchronization method

Synchronization method is to add synchronized keyword modification to the method
The above problem is solved using synchronous code blocks

package org.dennist.thread.demo;
/** * * TicketThreadR.java * * @version :  1.1 * * @author :  Su Ruonian < a href= "mailto: DennisIT@163.com"> Send mail</a>** @since :  1.0 Creation time: 02:29:23 * * TODO: class TicketThreadR. Java is used for...* */
public class TicketThreadR implements Runnable{
    
    private int num = 5;            //The total number of votes is set at 5.
    
    @Override
    public void run() {
        for(int i=0; i<10; i++){
            sale();                    //Call the synchronization method
        }
    }
    
    //Using synchronization method
    public synchronized void sale(){
        try {
            Thread.sleep(300);    //Rest 300 milliseconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }        
        if(this.num>0){    
            //Print ticket information
            System.out.println(Thread.currentThread().getName() + "Buy tickets: " + this.num--);
        }
    }
    
    public static void main(String[] args) {
        TicketThreadR ticketThread = new TicketThreadR();
        
        new Thread(ticketThread,"Ticket booth 1").start();    //Thread one
        new Thread(ticketThread,"Ticket outlet two").start();    //Thread one
        new Thread(ticketThread,"Ticket outlet three").start();    //Thread one
    }
}

 

Synchronization is required when multiple threads share the same resource, but too much synchronization can cause deadlock.

 

What is deadlock? What are the main causes of deadlocks? Necessary conditions for deadlock generation, how to solve deadlock?

Deadlock refers to the resource that each process in a group of processes waits indefinitely for another process in the restructured process to occupy and never release. This phenomenon is called system deadlock.

There are two main causes of deadlock:

1. Competitive resources, the limited number of resources provided by the system, can not meet the requirements of each process.

2. When multiprogramming runs, the sequence of process advancement is unreasonable.

Necessary conditions for deadlock generation

1. Mutual exclusive use of resources

2. Occupy and wait for resources

3. Do not seize resources.

4. Cyclic waiting for resources

Deadlock Solution

1. Preventing deadlocks: Breaking the conditions under which deadlocks occur (except for mutually exclusive conditions, which are unrealistic)

2. Avoid deadlocks

3. Detection and exclusion

4. Ignore it.

Reproduced in: https://my.oschina.net/u/580135/blog/612212

Keywords: Java REST

Added by dflow on Thu, 12 Sep 2019 10:20:43 +0300