Multithread Synchronization
Multithread security issues
Thread security problems are caused by global and static variables. If only read and write global and static variables in each thread
Generally speaking, this global variable is thread-safe; if multiple threads perform write operations at the same time, thread synchronization should be considered.
Otherwise, it may affect thread security.
For example, there is an example of this:
Simulated cinema tickets, there are 100 tickets, three windows sell tickets at the same time
Open three threads to sell the 100 tickets
Code:
public class Ticket implements Runnable { private int ticket = 100; /* * Perform ticket selling operation */ @Override public void run() { //The operation of selling tickets at each window //The window opens forever while (true) { if (ticket > 0) {//Tickets are available for sale. //Ticketing operation //Use sleep to simulate the ticketing time try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Gets the name of the current thread object String name = Thread.currentThread().getName(); System.out.println(name + "On sale:" + ticket); ticket--; }else{ break; } } } }
Selling tickets:
public class Test { public static void main(String[] args) throws InterruptedException { //Create Thread Task Objects Ticket ticket = new Ticket(); //Create three window objects Thread t1 = new Thread(ticket, "Window 1"); Thread t2 = new Thread(ticket, "Window 2"); Thread t3 = new Thread(ticket, "Window 3"); //Simultaneous selling of tickets t1.start(); t2.start(); t3.start(); } }
The final results are as follows:
There are two problems:
- The same number of tickets, such as five tickets, was sold twice.
- Non-existent tickets, such as 0 and - 1, do not exist.
This problem, the number of votes in several windows (threads) is not synchronized, which is the thread security problem.
The solution is to use multithreaded synchronization
So what is multithreaded synchronization?
According to examples, the following are briefly described:
-
When window 1 thread enters operation, window 2 and window 3 threads can only wait outside. When window 1 operation ends, window 1 and window 2 and window 3 have the opportunity to enter code to execute. That is to say, when a thread modifies the shared resources, other threads can not modify the resources. Only after the modification is completed, can they grab the CPU resources, complete the corresponding operations, ensure the synchronization of data, and solve the problem of thread insecurity.
Three Ways to Complete Synchronization Operation
The first way is to synchronize blocks of code
Synchronized (synchronized lock){ Code requiring synchronization }
Sync lock:
Object synchronization lock is just a concept, you can imagine marking a lock on the object.
- Lock objects can be of any type.
- Multiple threaded objects use the same lock.
Note: At most one thread is allowed to have a synchronization lock at any time. Anyone who gets the lock enters the code block. Other threads can only wait outside.
Code:
public class Ticket implements Runnable { private int ticket = 100; //Create a lock object Object lock = new Object(); /* * Perform ticket selling operation */ @Override public void run() { //The operation of selling tickets at each window //The window opens forever while (true) { synchronized (lock){ if (ticket > 0) {//Tickets are available for sale. //Ticketing operation //Use sleep to simulate the ticketing time try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Gets the name of the current thread object String name = Thread.currentThread().getName(); System.out.println(name + "On sale:" + ticket); ticket--; }else{ break; } } } } }
The final results are as follows:
Thread security issues are solved
The second method: synchronization method
The synchronized modified method is called synchronized method, which ensures that when thread A executes the method, other threads can only be outside the method.
Wait.
public synchronized void method(){ Code that may cause thread security problems }
Who is the synchronization lock here?
For non-static methods, the synchronization lock is this.
For the static method, we use the bytecode object (class name. class) of the class in which the current method resides.
Use code:
public class Ticket implements Runnable { private int ticket = 100; //Create lock objects //Object lock = new Object(); /* * Perform ticket selling operation */ @Override public void run() { //The operation of selling tickets at each window //The window opens forever while (true) { sellTicket(); if (ticket<=0){ break; } } } public synchronized void sellTicket(){ if (ticket > 0) {//Tickets are available for sale. //Ticketing operation //Use sleep to simulate the ticketing time try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Gets the name of the current thread object String name = Thread.currentThread().getName(); System.out.println(name + "On sale:" + ticket); ticket--; } } }
Result:
It also solves the thread thread security problem.
It's possible that all the code in the whole method needs to be synchronized. It's not particularly appropriate to use synchronized code blocks at this time. It's simpler to use synchronized methods.
The third method: Lock lock:
The java.util.concurrent.locks.Lock mechanism provides a wider locking operation than synchronized code blocks and synchronized methods.
Synchronized code block/synchronization method has the function of Lock, which is more powerful and more object-oriented.
There are two methods: locking and unlocking.
public void lock()//Add sync lock public void unlock()//Release synchronization lock
Note: Lock lock is an interface, so use its implementation class ReentrantLock to get the lock object
Use code:
public class Ticket implements Runnable { private int ticket = 100; //Create lock objects //Object lock = new Object(); //Create lock lock object Lock lock = new ReentrantLock(); /* * Perform ticket selling operation */ @Override public void run() { //The operation of selling tickets at each window //The window opens forever while (true) { lock.lock(); if (ticket > 0) {//Tickets are available for sale. //Ticketing operation //Use sleep to simulate the ticketing time try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Gets the name of the current thread object String name = Thread.currentThread().getName(); System.out.println(name + "On sale:" + ticket); ticket--; }else{ break; } lock.unlock(); } } }
Result:
It also solves the thread security problem.
These are the three ways to solve security problems.