Table of Contents
Multithreading:
Advantages of multithreading:
Disadvantages of multithreading:
Solution: Multi-thread synchronization
Locking method one: synchronized()
Inherit Thread()
Implement the Runnable interface
Locking method two: reentrantLock implements locking
Multi-threading:
In an application, there are multiple threads, and different threads can perform tasks in parallel.
Multi-threading advantages:
-
Improve program processing capabilities
For example: anti-virus software
-
Trash removal 1 minute.
-
Virus detection takes 1 minute.
-
-
Improve cpu utilization
-
Split large tasks (task manager)
-
Disadvantages of multi-threading:
-
The more threads, the more memory will be occupied (solved by hardware upgrade)
-
When multiple threads access shared resources simultaneously, thread safety issues may arise.
Solution: Multi-thread Synchronization
Locking: Only one thread can access shared resources at a time
Locking method one: synchronized()
Inherit Thread()
-
Decorate code blocks
synchronized modified code block
synchronized(synchronized object/lock){
}
Synchronization object: One object corresponding to multiple threads must be used to record whether any thread enters the synchronization code block; the synchronization object can be an object of any class in Java.
When there are multiple objects corresponding to synochronized
It is equivalent to creating multiple locks, but security problems will still occur. But you can create a public synchronization object to occupy the thread.
public class TicketThreadText { public static void main(String[] args) { TicketThread t1=new TicketThread(); t1.setName("Window 1"); TicketThread t2=new TicketThread(); t2.setName("Window 2"); t1.start(); t2.start(); } } public class TicketThread extends Thread{ static int t=10;//Unable to solve the problem, the run method may be entered at the same time, causing t to be entered as 10. static byte[] bytes=new byte[0];//The lock has no special meaning only to achieve synchronization of multiple objects//When the second object references bytes, it will be locked and wait for the first bytes to be processed /*synchronized modified code block ? Synchronization object: One object corresponding to multiple threads must be used to record whether any thread has entered the synchronization code block; A synchronization object can be an object of any class in Java. ? synchronized(synchronized object){ ? }*/ @Override public void run() { while(true){ synchronized(bytes) { if (t > 0) { System.out.println(Thread.currentThread().getName() + "Bought Chapter" + t + "ticket"); t--; } else { break; } } } } }
-
Modification method
synchronized modification method, the synchronization object will have the default one.
If the modified method is a non-static method, then the synchronization object is this.
If the modified method is a static method, then the synchronization object is the Class object of the current class.
Class object of the current class: When a class is loaded into memory, a unique Class object will be created for this class.
public class SynchronizedForTicketThread extends Thread{ static int t=10; ? @Override public void run() { thread(); } ? static public synchronized void thread() { while(true) { if(t<=0) { break; } else{ System.out.println(Thread.currentThread().getName() + "bought the first" + t + "chapter ticket"); t--; } } } } public class TicketThreadText { public static void main(String[] args) { SynchronizedForTicketThread t1=new SynchronizedForTicketThread(); t1.setName("Window 1"); SynchronizedForTicketThread t2=new SynchronizedForTicketThread(); t2.setName("Window 2"); t1.start();z t2.start(); } } ?
Implement Runnable interface
No need to use static methods to have only one task object
So just use synchronized modification directly
-
Decorate code blocks
public class RunnableForTicketThread implements Runnable { int t=10; @Override public void run() { while(true) { synchronized (this) { if (t > 0) { System.out.println(Thread.currentThread().getName() + "Out of Chapter" + t + "Chapter Ticket"); t--; } else { break; } } } } } public class RunnableTxet { public static void main(String[] args) { RunnableForTicketThread runnableForTicketThread=new RunnableForTicketThread(); Thread thread1=new Thread(runnableForTicketThread,"Window One"); Thread thread2=new Thread(runnableForTicketThread,"Window 2"); thread1.start(); thread2.start(); } } ?
-
Modification method
public class SynchronizedRunnableForTicket implements Runnable{ int t=10; @Override public void run() { thread(); } public synchronized void thread() { while(true) { if(t>0) { System.out.println(Thread.currentThread().getName() + "Bought the first ticket" + t + "ticket"); t--; } else {break;} } } } public class RunnableTxet { public static void main(String[] args) { SynchronizedRunnableForTicket synchronizedRunnableForTicket=new SynchronizedRunnableForTicket(); Thread thread1=new Thread(synchronizedRunnableForTicket,"Window One"); Thread thread2=new Thread(synchronizedRunnableForTicket,"Window Two"); thread1.start(); thread2.start(); } }
The result of running the above program is:
Locking method two: reentrantLock implements locking
public class ReentrantLookForTicketRunnable implements Runnable{ int t=10; ReentrantLock reentrantLock=new ReentrantLock(); @Override public void run() { while(t>1) { reentrantLock.lock(); try { System.out.println(Thread.currentThread().getName() + "Bought the first ticket" + t + "ticket"); t--; } finally { reentrantLock.unlock(); } } } } public class ReentrantLookText { public static void main(String[] args) { ReentrantLookForTicketRunnable reentrantLookForTicketRunnable = new ReentrantLookForTicketRunnable(); Thread thread1 = new Thread(reentrantLookForTicketRunnable, "Window One"); Thread thread2 = new Thread(reentrantLookForTicketRunnable, "Window Two"); thread1.start(); thread2.start(); } } ?
Similarity: they all implement the locking function
difference:
-
Synchronized is a keyword and ReentrantLock is a class
-
Synchronized modifies code blocks and methods, ReentrantLock can only modify code blocks
-
Synchronized can implicitly add and release locks, and can automatically release locks if an exception occurs during operation. ReentrantLock needs to manually add and release locks. It is recommended to release the lock in the finally code block.