Thread safety issues and how to solve them:
A security issue occurs when multiple threads are using a shared data
A classic case:
Cinemas sell tickets, a total of 100 seats, up to 100 tickets, buy tickets in a variety of ways, online purchase, self-ticketing machine, queuing to buy
Three ways to operate the same shared data, there are security issues:
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 () + "sell" +ticket--+ "Ticket"
Package Demo1; Public class Threaddemo { publicstaticvoid main (string[] args) { new tickets (); New Thread (t); New Thread (t); New Thread (t); T0.start (); T1.start (); T2.start (); }}
Generally there is no problem, but to think of it
However, assuming that only the last ticket is left, one thread grabs the CPU resource to execute, at the end of the judgment, the CPU resource is snatched by other threads, and the other threads are judged and executed
This time the start of the thread, because it has been judged, continue to execute, this time the number of votes will become negative, there is a problem
Workaround:
Synchronizing code blocks
Principle: When a thread enters a data operation, it prevents other threads from executing
PackageDemo1; Public classTicketsImplementsRunnable {Private intTicket = 100; PrivateObject obj1 =NewObject (); Public voidrun () { while(true) { synchronized(obj1) {if(Ticket > 0) {System.out.println (Thread.CurrentThread (). GetName ()+ "Sell First" + ticket--+ "Ticket"); } } } }}
However, although it is safe, the speed of operation is reduced.
However, we can disregard the speed for security, in any case, to ensure security
Here the incoming object parameter is abbreviated as: Synchronous lock, Professional name: Object monitor
Principle:
A thread that does not have a lock cannot execute, only waits for
When a thread encounters a synchronous block of code, it determines if there is a sync lock, and if so, takes away the lock, enters the synchronization and executes, and then locks the object back.
Another thread encounters a block of code without a lock, fails to enter, the original thread takes the lock back, and then the new thread acquires the lock, loops down
It is evident here that so much of the process slows down naturally.
Use the synchronous approach to solve the problem:
Pros: Lower code volume
PackageDemo1; Public classTicketsImplementsRunnable {Private intTicket = 100; Public voidrun () { while(true) {payticket (); } } Public synchronized voidPayticket () {//The object lock for a synchronous method is a reference to this class of objects://The lock of a static method is the class name. class if(Ticket > 0) {System.out.println (Thread.CurrentThread (). GetName ()+ "Sell First" + ticket--+ "Ticket"); } }}
Disadvantage: If an exception occurs, the lock object of the method is not released, no synchronization is made, and the lock is not released
A lock interface is required here:
Provides a wider range of locking operations
Improvements to previous ticketing cases:
PackageDemo1;ImportJava.util.concurrent.locks.Lock;ImportJava.util.concurrent.locks.ReentrantLock; Public classTicketsImplementsRunnable {Private intTicket = 100; PrivateLock lock =NewReentrantlock (); Public voidrun () { while(true) {lock.lock (); if(Ticket > 0) {System.out.println (Thread.CurrentThread (). GetName ()+ "Sell First" + ticket--+ "Ticket"); } lock.unlock (); } }}
Deadlock:
Disadvantages caused by synchronous locks:
When more than one synchronization occurs in a thread task, if other synchronizations are nested in the synchronization, then a phenomenon is raised, and the program waits indefinitely, a phenomenon called deadlock
Popular explanation: Two people eat a bowl of noodles, but only a pair of chopsticks, two people to grab a chopsticks, the rules can not be grabbed by hand, this time can not 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 () {} publicfinalstatic LOCKB lockb =new lockb ();}
PackageDemo1; Public classDeadLockImplementsRunnable {Private inti = 0; Public voidrun () { 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 { publicstaticvoid main (string[] args) { New DeadLock (); New Thread (dead); New Thread (dead); T0.start (); T1.start (); }}
After running, the card will not move at a certain place, but it does not stop.
Java Learning Note 45 (Multithreading II: Security issues and how to solve them)