多執行緒併發執行及解決方法
用一個案例來說明:假如我們要實現一個售票的小功能,用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執行緒
- 多執行緒高併發解決辦法執行緒
- 多執行緒併發篇——如何停止執行緒執行緒
- JAVA多執行緒併發Java執行緒
- 多執行緒與高併發(二)執行緒安全執行緒
- 併發與多執行緒之執行緒安全篇執行緒
- 多執行緒與高併發(一)多執行緒入門執行緒
- 多執行緒併發的一些解決思路執行緒
- java多執行緒詳解(併發,並行,同步)Java執行緒並行
- Java多執行緒/併發08、中斷執行緒 interrupt()Java執行緒
- 多執行緒程式設計,處理多執行緒的併發問題(執行緒池)執行緒程式設計
- java 多執行緒 併發 面試Java執行緒面試
- 如何解決多執行緒併發問題執行緒
- Java 併發和多執行緒(一) Java併發性和多執行緒介紹[轉]Java執行緒
- Java多執行緒/併發12、多執行緒訪問static變數Java執行緒變數
- 多執行緒併發安全問題詳解執行緒
- Java多執行緒與併發 - 瞭解“monitor”Java執行緒
- 【多執行緒與高併發】- 執行緒基礎與狀態執行緒
- Java多執行緒/併發06、執行緒鎖Lock與ReadWriteLockJava執行緒
- 併發與多執行緒基礎執行緒
- MySQL多執行緒併發調優MySql執行緒
- 多執行緒與併發----Semaphere同步執行緒
- Java併發和多執行緒:序Java執行緒
- Java高併發與多執行緒(三)-----執行緒的基本屬性和主要方法Java執行緒
- Java多執行緒/併發07、Thread.Join()讓呼叫執行緒等待子執行緒Java執行緒thread
- 多執行緒(五)---執行緒的Yield方法執行緒
- java多執行緒與併發 - 併發工具類Java執行緒
- 一文看懂JUC多執行緒及高併發執行緒
- Java併發(四)----執行緒執行原理Java執行緒
- Java併發 之 執行緒池系列 (1) 讓多執行緒不再坑爹的執行緒池Java執行緒
- Java高併發與多執行緒(二)-----執行緒的實現方式Java執行緒
- Java多執行緒/併發11、執行緒同步通訊:notify、waitJava執行緒AI
- Java 併發:執行緒、執行緒池和執行器全面教程Java執行緒
- 多執行緒的安全問題及解決方案執行緒
- 用多執行緒,實現併發,TCP執行緒TCP
- JAVA多執行緒和併發基礎Java執行緒