Causes of multithreading security problems
- Data shared by multiple threads
- There are multiple threads operating on shared data
- When one thread operates the shared data, other threads participate in the operation, which will lead to thread safety problems
Resolve thread safety issues
- Locking mechanism
- Idea: encapsulate the shared data. When a thread operates, other threads cannot participate in the operation. After the thread is executed, others can participate in the operation
- Synchronized code blocks can solve this problem: synchronized
Advantages and disadvantages of synchronization
- Benefits: resolve thread safety issues
- Disadvantages: the execution efficiency will be low, and the threads outside the synchronization will judge the synchronization lock
Lock used by synchronization function and synchronization code block
- The lock used by the synchronization function is this, fixed
- Synchronization code blocks can use any lock
- A lock is an object
Lock used by static synchronization function
- The lock used is the bytecode file Object to which the function belongs, that is, the class Object. It can be obtained by using the getClass method in the Object or represented by (current class name. Class)
How threads are created
- Inherit Thread
- Implement Runnbale
- The thread task is separated from the subclass of thread and encapsulated separately
- It avoids the limitation of Java single inheritance
- More commonly used
- callable
- Thread pool
Singleton mode under multithreading
- Hungry Han style
- The object is created as soon as the class is loaded
- Lazy style
- Create objects only when you want to use them
- Using singleton mode and hungry Chinese mode under multithreading is relatively simple to implement
- Lazy needs to be solved, thread insecurity and efficiency problems
Use synchronization to solve thread safety problems, and use if judgment to solve efficiency problems
//Lazy style class Single{ private static Single s = null; private Single(){} public static Single getInstance(){ if(s==null){ synchronized (Single.class){ if (s==null){ return new Single(); } } } return s; } }
Producer consumer model
Implementation of synchronized mode: in the case of multi consumer and multi producer mode, you can only use notifyAll(), and the use of notify() may deadlock.
package com.bixiangdong.thread; class Resource{ private String name; private int count=1; private boolean flag=false; public synchronized void set(String name){ while (flag){ try { this.wait(); }catch (InterruptedException e){ } } this.name=name; count++; System.out.println(Thread.currentThread().getName()+"----producer----"+this.name+count); flag=true; notifyAll();//notifyAll is used here because if there are multiple producers, the thread of the producer may always be awakened by notify, and then a deadlock may occur because flag = flag always waits } public synchronized void get(){ while (!flag){ try { this.wait(); }catch (InterruptedException e){ } } System.out.println(Thread.currentThread().getName()+"----consumer----"+this.name+count); flag=false; notifyAll(); } } class Productor implements Runnable{ private Resource r; public Productor(Resource r){ this.r=r; } @Override public void run() { while (true){ r.set("milk"); } } } class Customer implements Runnable{ private Resource r; public Customer(Resource r){ this.r=r; } @Override public void run() { while (true){ r.get(); } } } public class Demo03 { public static void main(String[] args) { Resource resource = new Resource(); Productor productor = new Productor(resource); Customer customer = new Customer(resource); new Thread(productor).start(); new Thread(customer).start(); } }
Lock implementation method: JDK1.5 supports the lock method, which can realize that a lock has multiple condition s, which can realize that the producer can notify the consumer more accurately. The producer can only wake up one consumer, and so can the consumer
package com.bixiangdong.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Resource2{ private String name; private int count=1; private boolean flag=false; //Create lock Lock lock = new ReentrantLock(); //Create two sets of monitors from existing locks Condition pro_con = lock.newCondition(); Condition cus_con = lock.newCondition(); public void set(String name){ //Set lock lock.lock(); while (flag){ try { pro_con.await(); }catch (InterruptedException e){ } } this.name=name; count++; System.out.println(Thread.currentThread().getName()+"----producer----"+this.name+count); flag=true; //notifyAll();// NotifyAll is used here because if there are multiple producers, the thread of the producer may always be awakened by notify, and then a deadlock may occur because flag = flag always waits cus_con.signal();//Just wake up one consumer //Release lock lock.unlock(); } public void get(){ lock.lock(); while (!flag){ try { cus_con.await(); }catch (InterruptedException e){ } } System.out.println(Thread.currentThread().getName()+"----consumer----"+this.name+count); flag=false; //notifyAll(); pro_con.signal(); lock.unlock(); } } class Productor2 implements Runnable{ private Resource2 r; public Productor2(Resource2 r){ this.r=r; } @Override public void run() { while (true){ r.set("milk"); } } } class Customer2 implements Runnable{ private Resource2 r; public Customer2(Resource2 r){ this.r=r; } @Override public void run() { while (true){ r.get(); } } } public class Demo04 { public static void main(String[] args) { Resource2 resource = new Resource2(); Productor2 productor = new Productor2(resource); Customer2 customer = new Customer2(resource); new Thread(productor).start(); new Thread(productor).start(); new Thread(productor).start(); new Thread(customer).start(); new Thread(customer).start(); new Thread(customer).start(); } }
The difference between wait and sleep
- wait can specify the time or not
- sleep must specify a time
During synchronization, the execution right of cpu is different from that of lock - wait: release the execution authority and release the lock
- sleep: release the execution authority without releasing the lock
End of thread
- If the run method in the thread ends, the thread ends
- How to end the run method by changing the flag
Marking method
package com.bixiangdong.thread; class A1 implements Runnable{ public boolean flag = true; @Override public void run() { while (flag){ System.out.println("Always running"+Thread.currentThread().getName()); } } } public class Demo05 { public static void main(String[] args) { A1 a1 = new A1(); new Thread(a1).start(); new Thread(a1).start(); int num=0; for (;;){ num++; if (num==100000){ a1.flag=false; break; // System.exit(0); } System.out.println("-----------"); } } }