In the process of selling tickets, there are thread safety problems, including duplicate tickets and wrong tickets. Why is this problem? When a thread has not completed the ticket selling operation during the operation of ticket selling, and other threads also participate in the operation of ticket selling, thread safety problems will occur (mainly the problem of shared data (nums)) How to solve this problem? When a thread is selling tickets, other threads cannot participate until the thread completes its operation (even if the thread is blocked, it must wait until the thread completes its execution). In java, we use synchronization mechanism to solve thread safety problems Method 1: synchronize code blocks Synchronized (synchronized monitor){ } explain: (1) The code that operates shared data is the code that needs to be synchronized. Too many codes that cannot be included will waste resources and reduce efficiency. (2) Shared data: variables operated by multiple threads, such as nums in ticket sales (3) Synchronization monitor is commonly known as lock. An object of any class can act as a lock, but only if the object is unique to multiple threads. Add: in the way of implementing the Runnable interface to create Thread objects, we can consider using this as the synchronization monitor. If we use the way of inheriting the Thread class For new thread objects, use This with caution (there may be multiple objects). You can use class. Class as the synchronization monitor.
package com.jinjian; /** In the process of selling tickets, there are thread safety problems, including duplicate tickets and wrong tickets. Why is this problem? When a thread has not completed the ticket selling operation during the operation of ticket selling, and other threads also participate in the operation of ticket selling, thread safety problems will occur (mainly the problem of shared data (nums)) How to solve this problem? When a thread is selling tickets, other threads cannot participate until the thread completes its operation (even if the thread is blocked, it must wait until the thread completes its execution). java Inside, we solve the thread safety problem through synchronization mechanism Method 1: synchronize code blocks synchronized(Synchronization monitor){ } explain: (1)The code that operates shared data is the code that needs to be synchronized. Too many codes that cannot be included will waste resources and reduce efficiency. (2)Shared data: variables operated by multiple threads, such as nums in ticket sales (3)Synchronization monitor is commonly known as lock. An object of any class can act as a lock, but only if the object is unique to multiple threads. Add: in the way of implementing the Runnable interface to create Thread objects, we can consider using this as the synchronization monitor. If we use the way of inheriting the Thread class For new thread objects, use This with caution (there may be multiple objects). You can use class. Class as the synchronization monitor. Mode 2: synchronization method */ class Window implements Runnable{ private int nums = 100; Object object = new Object(); @Override public void run() { while (true) { // synchronized (object) { synchronized (this) { if (nums > 0) { System.out.println(Thread.currentThread().getName() + "Ticket number: " + nums); nums--; } else { break; } } } } } class Window1 extends Thread{ private static int nums = 100; @Override public void run() { while (true) { synchronized (Window1.class) { if (nums > 0) { System.out.println(Thread.currentThread().getName() + "Ticket number: " + nums); nums--; } else { break; } } } } } public class ThreadTest03 { public static void main(String[] args) { //This is equivalent to creating three Window1 objects. If you want to share the num variable, you need to modify num with static. //Moreover, this cannot be used as the object monitor. Three this of three objects cannot guarantee the uniqueness of the object monitor //You can use Window1.class as an object monitor Window1 w1 = new Window1(); Window1 w2 = new Window1(); Window1 w3 = new Window1(); w1.start(); w2.start(); w3.start(); //Use the Runnable interface to create a new thread object // Window window = new Window(); //In this way, nums is a common variable, and static is not required, because only one Window object is created, and the following three thread objects share one Window object // Thread t1 = new Thread(window); // Thread t2 = new Thread(window); // Thread t3 = new Thread(window); // // t1.start(); // t2.start(); // t3.start(); } }
Use synchronization to solve thread safety problems, (1) The synchronization method still involves the synchronization monitor, but we don't need to explain it (2) The monitor of non static synchronization method is this by default, and the synchronization monitor of static method is the current class itself
package com.jinjian; /** Use synchronization to solve thread safety problems, (1)The synchronization method still involves the synchronization monitor, but we don't need to explain it (2)The monitor of non static synchronization method is this by default, and the synchronization monitor of static method is the current class itself */ class Window2 implements Runnable{ private int nums = 100; @Override public void run() { while (true) { seal(); } } private synchronized void seal(){//The default synchronization monitor is this if (nums > 0) { System.out.println(Thread.currentThread().getName() + "Ticket number: " + nums); nums--; } } } class Window3 extends Thread{ private static int nums = 100; @Override public void run() { while (true) { // synchronized (Window1.class) { seal(); //} } } // private synchronized void seal() {/ / this does not work. This is not the only one with three objects private static synchronized void seal(){//The default synchronization monitor is Window3.class if (nums > 0) { System.out.println(Thread.currentThread().getName() + "Ticket number: " + nums); nums--; } } } public class ThreadTest04 { public static void main(String[] args) { // Window2 window2 = new Window2(); // // Thread t1 = new Thread(window2); // Thread t2 = new Thread(window2); // Thread t3 = new Thread(window2); // // t1.start(); // t2.start(); // t3.start(); Window3 w1 = new Window3(); Window3 w2 = new Window3(); Window3 w3 = new Window3(); w1.start(); w2.start(); w3.start(); } }
Deadlock condition:
Demo program deadlock problem (1) 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 resources they need, forming a thread deadlock (2) There will be no exception or prompt after deadlock, but all threads are blocked and cannot continue. Therefore, deadlock should be avoided
(3) A thread waits to get the lock of s2 and releases the lock of s1 after execution. b thread waits to get the lock of s1 and releases the lock of s2 after execution. This forms a deadlock
package com.jinjian; import javax.swing.plaf.synth.SynthOptionPaneUI; /** Demo program deadlock problem (1)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 resources they need, forming a thread deadlock (2)There will be no exception or prompt after deadlock, but all threads are blocked and cannot continue. Therefore, deadlock should be avoided (3)a The thread waits to get the lock of s2 and releases the lock of s1 after execution. b the thread waits to get the lock of s1 and releases the lock of s2 after execution. This forms a deadlock */ public class TestThreadDeadLock { 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(); } }
Method 3 to solve thread safety problem: use lock ----------------- jdk5 to add Interview questions: Similarities and differences between Lock and synchronized? Same: both can solve thread safety problems Difference: the synchronized mechanism will automatically release the synchronization monitor after executing the corresponding code, Lock needs to start synchronization (lock) manually, and to end synchronization, it also needs to release the lock manually (unlock) Priority of several synchronization modes Lock ------ synchronized synchronized code block (has entered the method body and allocated corresponding resources) ----- synchronized method (outside the method body)
package com.jinjian; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** Method 3 to solve thread safety problem: use lock ----------------- jdk5 to add Interview questions: Lock And synchronized? Same: both can solve thread safety problems Difference: the synchronized mechanism will automatically release the synchronization monitor after executing the corresponding code, Lock You need to manually start the synchronization (lock), and you also need to manually release the lock (unlock) to end the synchronization Priority of several synchronization modes Lock-----synchronized Synchronized code block (has entered the method body and allocated corresponding resources) --- synchronized method (outside the method body) */ class Window5 implements Runnable{ private int nums = 100; //Instantiate ReentrantLock private ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true) { try { //Lock, the code blocks between locks will be locked, which is the same as the code blocks enclosed by synchronized to achieve thread safety lock.lock(); if (nums > 0) { System.out.println(Thread.currentThread().getName() + "Ticket number: " + nums); nums--; } else { break; } }finally { //Unlock lock.unlock(); } } } } public class TestReentrantLock { public static void main(String[] args) { Window5 window5 = new Window5(); Thread t1 = new Thread(window5); Thread t2 = new Thread(window5); Thread t3 = new Thread(window5); t1.start(); t2.start(); t3.start(); } }