多執行緒併發執行及解決方法
用一個案例來說明:假如我們要實現一個售票的小功能,用3個執行緒售出共2000張票。
初始模型為:
package com.test7;
public class synchronizedTest {
public static void main(String [] args){
TicketWindow tw = new TicketWindow();
Thread t1 = new Thread(tw);
Thread t2 = new Thread(tw);
Thread t3 = new Thread(tw);
t1.start();
t2.start();
t3.start();
}
}
class TicketWindow implements Runnable{
int nums = 2000;
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(nums>0){
System.out.println(Thread.currentThread().getName()+"當前正在售出弟"+nums+"張票");
nums--;
}
else{
break;
}
}
}
}
程式碼執行結果為:
但是我們發現這3個執行緒會出現同時售出一張票的情況,這是怎麼回事呢?以售出第1766張票為例,因為這3個執行緒是多執行緒併發執行的,當其中一個執行緒Thread-2訪問第1766張票時,進入if語句,執行完
System.out.println(Thread.currentThread().getName()+"當前正在售出弟"+nums+"張票");
這條語句而還未執行nums--時,另一個執行緒Thread-1也開始訪問第1766張票,進入了if語句,開始執行
System.out.println(Thread.currentThread().getName()+"當前正在售出弟"+nums+"張票");
此時便會同時售出兩張1766張票。
我們知道,這種執行緒是極其危險的,那麼怎麼解決,讓執行緒變得安全呢?
其實很簡單,只需要加一個物件鎖,什麼是物件鎖呢?別急,往下看。
如果我們把上面執行緒併發執行的過程抽象成上廁所的話,就一個馬桶,很多個人在外面排隊,如果兩個或者多個人程同時上一個廁所,就很容易出現問題,這種執行緒是不安全的。要解決問題只需要在門上安一把鎖,必須等上一個人解決了下一個人才能進入,要解決的一個一個來。(擴充套件一下,會不會有一直解決不了的情況呢?會,比如當一個執行緒a在A廁所中執行執行緒,執行緒b等a解決完了才能進入A廁所,而a執行過程中要呼叫B廁所,而B廁所正好有人在裡面了,這個人正好是B。這樣的話,執行緒A永遠結束不了,就出現了死鎖問題)
我們解決上述問題的方法就是加個物件鎖,物件鎖有0和1兩種狀態,預設情況為1,代表廁所裡沒人,執行緒可以進入。一旦執行緒進入,她就會變成0---有人的狀態,其他執行緒不能進入,不能進入的執行緒會進入執行緒等待池中(blocked阻塞狀態)。任何物件都可以充當物件鎖,一般用this充當物件鎖。
程式碼是
synchronized (Object) {要執行緒同步的程式碼塊}
最終修改程式碼為:
package com.test7;
public class synchronizedTest {
public static void main(String [] args){
TicketWindow tw = new TicketWindow();
Thread t1 = new Thread(tw);
Thread t2 = new Thread(tw);
Thread t3 = new Thread(tw);
t1.start();
t2.start();
t3.start();
}
}
class TicketWindow implements Runnable{
int nums = 2000;
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
if (nums > 0) {
System.out.println(Thread.currentThread().getName() + "當前正在售出弟" + nums + "張票");
nums--;
} else {
break;
}
}
}
}
}
執行結果為:
相關文章
- 多執行緒併發同步問題及解決方案執行緒
- java多執行緒與併發 - 執行緒池詳解Java執行緒
- 多執行緒併發篇——如何停止執行緒執行緒
- 併發與多執行緒之執行緒安全篇執行緒
- 多執行緒與高併發(二)執行緒安全執行緒
- JAVA多執行緒併發Java執行緒
- 多執行緒與高併發(一)多執行緒入門執行緒
- 多執行緒併發的一些解決思路執行緒
- 如何解決多執行緒併發問題執行緒
- 多執行緒併發安全問題詳解執行緒
- 多執行緒(五)---執行緒的Yield方法執行緒
- Java高併發與多執行緒(三)-----執行緒的基本屬性和主要方法Java執行緒
- 【多執行緒與高併發】- 執行緒基礎與狀態執行緒
- Python《多執行緒併發爬蟲》Python執行緒爬蟲
- 併發與多執行緒基礎執行緒
- 多執行緒與併發----Semaphere同步執行緒
- MySQL多執行緒併發調優MySql執行緒
- Python執行緒安全問題及解決方法Python執行緒
- Java併發 之 執行緒池系列 (1) 讓多執行緒不再坑爹的執行緒池Java執行緒
- 一文看懂JUC多執行緒及高併發執行緒
- python基礎執行緒-管理併發執行緒Python執行緒
- Java併發(四)----執行緒執行原理Java執行緒
- Java高併發與多執行緒(二)-----執行緒的實現方式Java執行緒
- java多執行緒與併發 - 併發工具類Java執行緒
- Java 併發:執行緒、執行緒池和執行器全面教程Java執行緒
- 66.QT-執行緒併發、QTcpServer併發、QThreadPool執行緒池QT執行緒TCPServerthread
- 多執行緒的安全問題及解決方案執行緒
- 多執行緒之間通訊及執行緒池執行緒
- 小度分享-【多執行緒工作及執行緒安全】執行緒
- 執行緒與多執行緒執行緒
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- Java—執行緒的生命週期及執行緒控制方法詳解Java執行緒
- Java多執行緒與併發之ThreadLocalJava執行緒thread
- 用多執行緒,實現併發,TCP執行緒TCP
- Java併發/多執行緒-CAS原理分析Java執行緒
- 多執行緒與併發----讀寫鎖執行緒
- HashMap多執行緒併發問題分析HashMap執行緒