1. Background
Example: create a window to sell tickets, and the total number of tickets is 100 Use the way to implement the Runnable interface
*
- 1. Problem: in the process of selling tickets, there are duplicate tickets and wrong tickets -- > there are thread safety problems
- 2. Cause of the problem: when a thread is operating the ticket and the operation has not been completed, other threads participate and operate the ticket.
- 3. How to solve it: when a thread a is operating a ticket, other threads cannot participate. No other thread can start to operate the ticket until thread a has finished operating the ticket. This situation cannot be changed even if thread a is blocked.
class Window implements Runnable { private int ticket = 100; @Override public void run() { while (true) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + ticket--); } else { break; } } } } public class ThreadTest { public static void main(String[] args) { Window myThread = new Window(); Thread thread1 = new Thread(myThread); Thread thread2 = new Thread(myThread); Thread thread3 = new Thread(myThread); thread1.start(); thread2.start(); thread3.start(); } }
2.Java solution: synchronization mechanism
In Java, we solve the thread safety problem through synchronization mechanism.
Method 1: synchronize code blocks
* * synchronized(Synchronization monitor){ * //Code to be synchronized * * } @Override public void run() { while (true) { synchronized (obj) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":" + ticket--); } else { break; } } } }
- Description: 1 The code that operates the shared data is the code that needs to be synchronized. -- > It cannot contain more code or less code.
-
2.Shared data: variables operated by multiple threads. For example: ticket Is sharing data.
-
3.Synchronous monitor, commonly known as lock. The object of any class can act as a lock.
-
Requirement: multiple threads must share the same lock.
- Add: in the way of implementing Runnable interface to create multithreading, we can consider using this as the synchronization monitor.
In the way of inheriting the Thread class to create multithreads, use this as the synchronization monitor with caution, and consider using the current class as the synchronization monitor.
Mode 2: synchronization method
* If the code that operates on shared data is completely declared in a method, we might as well synchronize this method declaration. * Summary of synchronization methods: * 1. The synchronization method still involves the synchronization monitor, but we don't need to declare it explicitly. * 2. Non static synchronization method. The synchronization monitor is: this * The current method of the monitor class is static synchronization
Mode 3: Lock - jdk5 0 NEW
-
- Interview question: what are the similarities and differences between synchronized and Lock?
- Same: both can solve thread safety problems
- Difference: the synchronized mechanism automatically releases the synchronization monitor after executing the corresponding synchronization code
- Lock requires manual start synchronization (lock(), and manual implementation (unlock()) to end synchronization
Priority of use:
- Lock - > synchronize code block (has entered the method body and allocated corresponding resources) - > synchronize method (outside the method body)
3. Advantages and disadvantages
The way of synchronization solves the problem of thread safety benefit
When operating synchronization code, only one thread can participate and other threads wait. It is equivalent to a single threaded process with low efficiency.
4. Interview questions:
How does Java solve thread safety problems? How many ways? And compare the differences of several ways
Interview question: comparison of synchronized and Lock methods to solve thread safety problems
Thread safe singleton mode (lazy)
Use the synchronization mechanism to rewrite the lazy style in singleton mode to thread safe.
class Bank{ private Bank(){} private static Bank instance = null; public static Bank getInstance(){ //Mode 1: slightly less efficient // synchronized (Bank.class) { // if(instance == null){ // // instance = new Bank(); // } // return instance; // } //Mode 2: higher efficiency if(instance == null){ synchronized (Bank.class) { if(instance == null){ instance = new Bank(); } } } return instance; } }
Interview question: write a thread safe singleton mode.
Hungry man style.
Lazy: provided above.
Deadlock problem
1. Understanding of Deadlock:
Different threads occupy the synchronization resources needed by the other party and do not give up. They are waiting for the other party to give up the synchronization resources they need, forming a thread deadlock
2. Description:
- 1. After deadlock occurs, there will be no exception or prompt, but all threads are blocked and cannot continue
- 2 when we use synchronization, we should avoid deadlock.
3. Examples:
public static void main(String[] args) { StringBuffer s1 = new StringBuffer(); StringBuffer s2 = new StringBuffer(); new Thread(){ @Override public void run() { synchronized (s1){ s1.append("a"); s2.append("1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s2){ s1.append("b"); s2.append("2"); System.out.println(s1); System.out.println(s2); } } } }.start(); new Thread(new Runnable() { @Override public void run() { synchronized (s2){ s1.append("c"); s2.append("3"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1){ s1.append("d"); s2.append("4"); System.out.println(s1); System.out.println(s2); } } } }).start(); }