Java Study Notes 45 (multithreading 2: security issues and solutions), java Study Notes
Thread security issues and solutions:
Security issues occur when multiple threads use one shared data.
A classic case:
Tickets are sold in cinemas, with a total of 100 seats and a maximum of 100 tickets. There are many ways to buy tickets, such as online purchase, self-owned ticket vending machine, and queuing purchase.
When you operate the same shared data in three ways, security issues may occur:
Example:
Package demo1; public class Tickets implements Runnable {private int ticket = 100; public void run () {while (true) {if (ticket> 0) {System. out. println (Thread. currentThread (). getName () + "Sale No." + ticket -- + "ticket ");}}}}
package demo1;public class ThreadDemo { public static void main(String[] args) { Tickets t = new Tickets(); Thread t0 = new Thread(t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t0.start(); t1.start(); t2.start(); }}
Generally, no problem occurs, but you need to think of this problem.
However, if only the last ticket is left, one thread grabs the CPU resource for execution. At the end of the judgment, the CPU resource is snatched by other threads, and the other threads judge and execute,
At this time, the thread at the beginning will continue to execute because it has been judged, and the number of votes will change to a negative number, so there is a problem here.
Solution:
Synchronous Code Block
Principle: When a thread enters a data operation, other threads are prevented from executing the operation.
Package demo1; public class Tickets implements Runnable {private int ticket = 100; private Object obj1 = new Object (); public void run () {while (true) {synchronized (obj1) {if (ticket> 0) {System. out. println (Thread. currentThread (). getName () + "Sale No." + ticket -- + "ticket ");}}}}}
However, although it is safe, the operation speed is reduced.
However, we need to ensure security regardless of the speed.
The object parameter referred to here is synchronization lock, professional name: Object Monitor
Principle:
Threads without locks cannot be executed and can only wait.
When a thread encounters a synchronization code block, it determines whether a synchronization lock exists. If yes, it takes the lock away and enters the synchronization for execution. After the execution is complete, the lock object is returned.
When another thread encounters a code block, there is no lock and it cannot enter. After the original thread returns the lock, the new thread obtains the lock and loops down.
It can be seen that the speed of so many processes naturally slows down.
Solve the problem through synchronization:
Advantage: less code
Package demo1; public class Tickets implements Runnable {private int ticket = 100; public void run () {while (true) {payTicket () ;}} public synchronized void payTicket () {// The object lock of the synchronization method is referenced by this class object: that is, the lock of this // static method is the class name of this class. class if (ticket> 0) {System. out. println (Thread. currentThread (). getName () + "Sale No." + ticket -- + "ticket ");}}}
Disadvantage: if an exception occurs, the Lock Object of the method is not released and cannot be synchronized. The lock is not released.
Here we need to use a Lock interface:
Provides a wider range of lock operations
Improve the previous ticket sales case:
Package demo1; import java. util. concurrent. locks. lock; import java. util. concurrent. locks. reentrantLock; public class Tickets implements Runnable {private int ticket = 100; private Lock lock = new ReentrantLock (); public void run () {while (true) {lock. lock (); if (ticket> 0) {System. out. println (Thread. currentThread (). getName () + "sale number" + ticket -- + "ticket");} lock. unlock ();}}}
Deadlock:
Disadvantages caused by synchronization lock:
When multiple synchronization occurs in a thread task, if other synchronization is nested in the synchronization, this will lead to a phenomenon where the program waits infinitely, which is called a deadlock.
In plain text: two people eat a bowl of noodles, but they only have a pair of chopsticks. One person grabs a pair of chopsticks, and requires that they cannot catch them by hand. At this time, they cannot eat noodles.
Code implementation:
package demo1;public class LockA { private LockA(){} public final static LockA locka =new LockA();}
package demo1;public class LockB { private LockB(){} public final static LockB lockb =new LockB();}
package demo1;public class DeadLock implements Runnable { private int i = 0; public void run() { while (true) { if (i % 2 == 0) { synchronized (LockA.locka) { System.out.println("if...locka"); synchronized (LockB.lockb) { System.out.println("if...lockb"); } } } else { synchronized (LockB.lockb) { System.out.println("else...lockb"); synchronized (LockA.locka) { System.out.println("else...locka"); } } } i++; } }}
package demo1;public class DeadLockDemo { public static void main(String[] args) { DeadLock dead = new DeadLock(); Thread t0 = new Thread(dead); Thread t1 = new Thread(dead); t0.start(); t1.start(); }}
After running, it is found that it will be stuck in a certain place, but it has not stopped