生活随笔
收集整理的這篇文章主要介紹了
多线程安全问题1
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.問題的產(chǎn)生
原因:多個(gè)線程操作同一個(gè)共享數(shù)據(jù)。
原理:多個(gè)線程在訪問共享數(shù)據(jù)時(shí),由于CPU的隨機(jī)性,一個(gè)線程還沒有執(zhí)行完,執(zhí)行權(quán)被其他線程搶走了,這個(gè)時(shí)候就有可能出現(xiàn)線程安全問題。
解決方式:把操作共享數(shù)據(jù)的代碼鎖起來,讓單一線程執(zhí)行完畢才能執(zhí)行其他的
2.解決方法【上鎖】
三種方法的測(cè)試類【測(cè)試類相同】
public class Demo {public static void main(String[] args
) {TicketRunnable ticketRunnable
= new TicketRunnable();Thread thread1
= new Thread(ticketRunnable
);Thread thread2
= new Thread(ticketRunnable
);Thread thread3
= new Thread(ticketRunnable
);thread1
.setName("1號(hào)窗口---");thread1
.start();thread2
.setName("2號(hào)窗口---");thread2
.start();thread3
.setName("3號(hào)窗口---");thread3
.start();}
}打印結(jié)果:
----------------------------------------------------------------------------------------------------
2號(hào)窗口
---賣了一張票
,還剩
2張票
3號(hào)窗口
---賣了一張票
,還剩
1張票
3號(hào)窗口
---賣了一張票
,還剩
0張票
<1>同步代碼塊
鎖對(duì)象:可以是任意對(duì)象,但是要保證唯一;
synchronized(鎖對(duì)象){
多個(gè)線程訪問共享數(shù)據(jù)的代碼
}
public class TicketRunnable implements Runnable {int ticket
= 100;@Overridepublic void run() {while (true) {synchronized (TicketRunnable.class){if (ticket
<=0){break;}else {try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}ticket
--;System.out
.println(Thread.currentThread().getName()+"賣了一張票,還剩" + ticket
+ "張票");}}}}
}
<2>同步方法/靜態(tài)同步方法
同步方法:一個(gè)線程執(zhí)行這個(gè)方法,另一個(gè)線程就必須等待;
同步方法的鎖對(duì)象:this
public class TicketRunnable implements Runnable {private static int ticket
=100;@Overridepublic void run() {while (true) {boolean flag
= method();if(flag
){break;}}}private static synchronized boolean method() {if (ticket
<=0){return true;}else {try {Thread.sleep(100);} catch (InterruptedException e
) {e
.printStackTrace();}ticket
--;System.out
.println(Thread.currentThread().getName()+"賣了一張票,還剩" + ticket
+ "張票");return false;}}
}
<3>lock鎖手動(dòng)上鎖和解鎖
ReentrantLock lock = new ReentrantLock(); //【具體子類或者實(shí)現(xiàn)類】創(chuàng)建鎖對(duì)象
//上鎖
lock.lock(); //一個(gè)線程執(zhí)行到這里,其他線程就必須在這里等
//有可能產(chǎn)生安全問題的代碼
//解鎖
lock.unlock(); //等這個(gè)線程執(zhí)行完了,其他線程才能進(jìn)來執(zhí)行。
public class TicketRunnable implements Runnable {private int ticket
= 100;ReentrantLock lock
= new ReentrantLock();@Overridepublic void run() {while (true) {try {lock
.lock();if (ticket
<= 0) {break;} else {Thread.sleep(100);ticket
--;System.out
.println(Thread.currentThread().getName() + "賣了一張票,還剩" + ticket
+ "張票");}} catch (Exception e
) {e
.printStackTrace();} finally {lock
.unlock();}}}
}
3.死鎖情況【面試】
產(chǎn)生條件:就是鎖的嵌套導(dǎo)致
概念:當(dāng)其他線程持有對(duì)方所需要的資源,導(dǎo)致這些線程處理等待狀態(tài),無法繼續(xù)執(zhí)行
public class Demo1 {public static void main(String[] args
) {Object objA
= new Object();Object objB
= new Object();new Thread (() -> {while (true){synchronized (objA
){synchronized (objB
){System.out
.println("小康同學(xué)正在走路");}}}}).start();new Thread(() -> {while (true){synchronized (objB
){synchronized (objA
){System.out
.println("小微同學(xué)正在走路");}}}}).start();}
}打印結(jié)果:【程序不結(jié)束,且也無法向前運(yùn)行】
----------------------------------------------------------------------------------------------------
小康同學(xué)正在走路
小康同學(xué)正在走路
小康同學(xué)正在走路
小康同學(xué)正在走路
小康同學(xué)正在走路
結(jié)果分析:
正常情況:小康走完objA和objB,A,B鎖正常開閉;
異常情況:小康走過objA,A鎖關(guān)閉,此時(shí)小薇同學(xué)走過objB,B鎖關(guān)閉,次數(shù)A,B鎖都關(guān)閉,導(dǎo)致死鎖。
總結(jié)
以上是生活随笔為你收集整理的多线程安全问题1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。