java 執行緒安全問題,解決執行緒安全問題——同步程式碼塊,同步方法,Lock鎖,Object類中wait方法,notify方法。等待喚醒案例。
1、執行緒安全問題
執行緒出現安全問題的程式碼:
/*
實現賣票案例
*/
public class RunnableImpl implements Runnable{
//定義一個多個執行緒共享的票源
private int ticket = 100;
//設定執行緒任務:賣票
@Override
public void run() {
//使用死迴圈,讓買票操作重複執行
while (true) {
//先判斷票是否存在
if (ticket > 0) {
//提高安全問題出現的概率,讓程式睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,賣票ticket
System.out.println(Thread.currentThread().getName() + "正在賣第"+ticket+"張票");
ticket--;
}
}
}
}
主類:
/*
模擬賣票案例
建立三個執行緒,同時開啟,對共享的票進行出售
*/
public class Demo01Ticket {
public static void main(String[] args) {
//建立Runnable介面的實現類物件
RunnableImpl run = new RunnableImpl();
//建立Thread類物件,構造方法中傳遞Runnable介面的實現類物件
Thread t0 = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
//呼叫start方法開啟多執行緒
t0.start();
t1.start();
t2.start();
}
}
執行截圖:
三個執行緒賣了同一張票,即安全問題。
2、解決執行緒安全問題—同步程式碼塊
同步程式碼塊:synchronized關鍵字可以用於方法中的某個區塊中,表示只對這個區塊的資源實現互斥訪問。
格式:
synchronized(同步鎖){
需要同步操作的程式碼
}
使用程式碼:
/*
實現賣票案例出現了執行緒安全問題,賣出了不存在的票和重複的票
解決執行緒安全問題的第一種方案:使用同步程式碼塊
格式:
synchronized(同步鎖){
需要同步操作的程式碼
}
注意:
1、通過程式碼塊中的鎖物件,可以使用任意的物件
2、但是必須保證多個執行緒使用的鎖物件是同一個
3、鎖物件作用:
把同步程式碼塊鎖住,只讓一個執行緒在同步程式碼塊中執行
*/
public class RunnableImpl implements Runnable{
//定義一個多個執行緒共享的票源
private int ticket = 100;
//建立一個鎖物件
Object obj = new Object();
//設定執行緒任務:賣票
@Override
public void run() {
//使用死迴圈,讓買票操作重複執行
while (true) {
//同步程式碼塊
synchronized (obj){
//先判斷票是否存在
if (ticket > 0) {
//提高安全問題出現的概率,讓程式睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,賣票ticket
System.out.println(Thread.currentThread().getName() + "正在賣第"+ticket+"張票");
ticket--;
}
}
}
}
}
主程式碼不變。
3、解決執行緒安全問題——同步方法
解決執行緒安全的第二種方案:使用同步方法
使用步驟:
1、把訪問了共享資料的程式碼抽取出來,放到一個方法中
2、在方法上新增synchronized修飾符
格式:定義方法的格式
修飾符 synchronized 返回值型別 方法民(引數列表) {
可能出現執行緒安全問題的程式碼(訪問了共享資料的程式碼)
}
程式碼:
/*
實現賣票案例出現了執行緒安全問題
解決執行緒安全的第二種方案:使用同步方法
*/
public class RunnableImpl implements Runnable{
//定義一個多個執行緒共享的票源
private int ticket = 100;
//設定執行緒任務:賣票
@Override
public void run() {
//使用死迴圈,讓買票操作重複執行
while (true) {
payTicket();
}
}
/*
定義同步方法
*/
public synchronized void payTicket() {
//先判斷票是否存在
if (ticket > 0) {
//提高安全問題出現的概率,讓程式睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,賣票ticket
System.out.println(Thread.currentThread().getName() + "正在賣第"+ticket+"張票");
ticket--;
}
}
}
4、解決執行緒安全問題——Lock鎖
Lock鎖也稱同步鎖,加鎖與釋放鎖方法化了,如下:
public void lock( ) :加同步鎖
public void unlock( ) :釋放同步鎖
程式碼及使用步驟如下:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
實現賣票案例
出現了執行緒安全問題
解決執行緒安全問題的第三種方案:使用Lock鎖
java.util.concurrent.Locks.Lock介面
Lock實現提供了比使用synchronized方法和語句可獲得的更廣泛的鎖定操作。
Lock介面中的方法:
public void lock( ) :加同步鎖
public void unlock( ) :釋放同步鎖
java.util.concurrent.locks.ReentrantLock implements Lock介面
使用步驟:
1、在成員位置建立一個ReentrantLock物件
2、可能會出現安全問題的程式碼前呼叫lock介面中的方法lock獲取鎖
3、可能會出現安全問題的程式碼後呼叫lock介面中的方法unlock釋放鎖
*/
public class RunnableImpl implements Runnable{
//定義一個多個執行緒共享的票源
private int ticket = 100;
// 1、在成員位置建立一個ReentrantLock物件
Lock l = new ReentrantLock();
//設定執行緒任務:賣票
@Override
public void run() {
//使用死迴圈,讓買票操作重複執行
while (true) {
// 2、可能會出現安全問題的程式碼前呼叫lock介面中的方法lock獲取鎖
l.lock();
//先判斷票是否存在
if (ticket > 0) {
//提高安全問題出現的概率,讓程式睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,賣票ticket
System.out.println(Thread.currentThread().getName() + "正在賣第"+ticket+"張票");
ticket--;
}
// 3、可能會出現安全問題的程式碼後呼叫lock介面中的方法unlock釋放鎖
l.unlock();
}
}
}
5、幾種執行緒的狀態
Timed Waiting 計時等待
Blocked 鎖阻塞狀態
Waiting 無限等待
6、等待喚醒案例
程式碼:
/*
等待喚醒案例:執行緒之間的通訊
建立一個顧客執行緒,告知老闆要的包子的種類和數量,呼叫wait方法,放棄cpu的執行,進入到
waiting狀態(無限等待)
建立一個老闆執行緒(生產者):花了5秒做包子,做好包子之後,呼叫notify方法,喚醒顧客吃包子
注意:
1、顧客和老闆執行緒必須使用同步程式碼塊包裹起來,保證等待和喚醒只能有一個在執行
2、同步使用的鎖物件必須保證是唯一的
3、只有鎖物件才能呼叫wait和notify方法
Object類中的方法
void wait()
在其他執行緒呼叫此物件的notify()方法或者notifyAll()方法前,導致當前執行緒等待
void notify()
喚醒在此物件監視器上等待的單個執行緒。
會繼續執行wait方法之後的程式碼
*/
public class Demo01WaitAndNotify {
public static void main(String[] args) {
//建立鎖物件,保證唯一
Object obj = new Object();
//建立一個顧客執行緒
new Thread(){
@Override
public void run() {
while (true) { //一直有顧客買包子
//保證等待和喚醒的執行緒只能有一個在執行,同步技術
synchronized (obj) {
System.out.println("告訴老闆要的包子的種類和數量");
//呼叫wait方法,放棄cpu的執行,進入到waiting狀態(無限等待)
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//喚醒之後執行的程式碼
System.out.println("包子已經做好了,開吃");
System.out.println("——————————————————————");
}
}
}
}.start();
//建立一個老闆執行緒(生產者)
new Thread(){
@Override
public void run() {
//一直做包子
while (true) {
//花了5秒做包子
try {
Thread.sleep(5000); //5秒做包子
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("老闆5秒之後做好包子,告知顧客可以吃了");
//呼叫notify方法,喚醒顧客吃包子
obj.notify();
}
}
}
}.start();
}
}
執行截圖:
7、Object類中wait帶參方法和notifyAll方法
進入到TimeWaiting(計時等待)有兩種方式
1、使用sleep(long m)方法,在毫秒值結束之後,執行緒睡醒進入到Runnable/Blocked狀態
2、使用wait(long m)方法,wait方法如果在毫秒值結束之後,還沒有被notify喚醒,就會自動醒來,執行緒睡醒進入到Runnable/Blocked狀態
喚醒的方法:
void notify( )喚醒單個執行緒
void notifyAll( )喚醒所有執行緒。
相關文章
- 【Java】【多執行緒】同步方法和同步程式碼塊、死鎖Java執行緒
- Python執行緒安全問題及解決方法Python執行緒
- 模板方法中的執行緒安全問題執行緒
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- Java多執行緒中wait 和 notify 方法理解Java執行緒AI
- 執行緒同步方法執行緒
- Java中解決多執行緒資料安全問題Java執行緒
- Python | 多執行緒死鎖問題的巧妙解決方法Python執行緒
- Java之執行緒安全問題的3種處理方式(通過執行緒同步)Java執行緒
- 深入JAVA執行緒安全問題Java執行緒
- 執行緒虛假喚醒問題剖析執行緒
- java多執行緒:執行緒同步synchronized(不同步的問題、佇列與鎖),死鎖的產生和解決Java執行緒synchronized佇列
- 03 執行緒安全問題執行緒
- SimpleDateFormat 執行緒安全問題ORM執行緒
- Java 多執行緒基礎(六)執行緒等待與喚醒Java執行緒
- parallelStream中的執行緒安全問題Parallel執行緒
- Java多執行緒之執行緒同步【synchronized、Lock、volatitle】Java執行緒synchronized
- Java24解決了虛擬執行緒同步使用問題Java執行緒
- 多執行緒併發同步問題及解決方案執行緒
- Java 執行緒安全問題的本質Java執行緒
- java多執行緒基礎篇(wait、notify、join、sleep、yeild方法)Java執行緒AI
- ArrayList 的執行緒安全問題執行緒
- JAVA多執行緒詳解(3)執行緒同步和鎖Java執行緒
- 多執行緒,你覺得你安全了?(執行緒安全問題)執行緒
- 多執行緒的安全問題及解決方案執行緒
- lambda中stream執行緒安全的問題執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- 執行緒間的同步與通訊(2)——wait, notify, notifyAll執行緒AI
- String中hashCode方法的執行緒安全執行緒
- Java多執行緒程式設計(同步、死鎖、生產消費者問題)Java執行緒程式設計
- 多執行緒併發安全問題詳解執行緒
- JUC之集合中的執行緒安全問題執行緒
- java 執行緒淺解03[執行緒同步以及經典死鎖]Java執行緒
- 執行緒安全(三個條件)Synchronzied,wait和notify執行緒AI
- java執行緒執行緒休眠,sleep方法Java執行緒
- Java多執行緒學習(四)等待/通知(wait/notify)機制Java執行緒AI
- JUC之多執行緒鎖問題執行緒
- 6.JUC執行緒高階-Lock同步鎖執行緒