摘要:當多個線程同時共享,同一個全局變量或靜態變量,做寫的操作時,可能會發生數據沖突問題,也就是線程安全問題。
當多個線程同時共享,同一個全局變量或靜態變量,做寫的操作時,可能會發生數據沖突問題,也就是線程安全問題。但是做讀操作是不會發生數據沖突問題
模擬線程安全問題public class SafeThread implements Runnable { private int ticketCount = 50; @Override public void run() { while (ticketCount > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); ticketCount--; } } }
@RequestMapping("test-safe") public void testSafe() { SafeThread safeThread = new SafeThread(); Thread t1 = new Thread(safeThread, "thread-1"); Thread t2 = new Thread(safeThread, "thread-2"); t1.start(); t2.start(); }
結果:火車票會重復出售
解決辦法使用多線程之間同步synchronized或使用鎖(lock)
1.同步代碼塊
public class SafeThread implements Runnable { private int ticketCount = 50; @Override public void run() { while (ticketCount > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (this) { System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); ticketCount--; } } } }
2.同步方法
public class SafeThread implements Runnable { private int ticketCount = 50; @Override public void run() { while (ticketCount > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } // synchronized (this) { // System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); // ticketCount--; // } sale(); } } private synchronized void sale() { System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); ticketCount--; } }
注意:同步函數使用this鎖
3.靜態同步函數
方法上加上static關鍵字,使用synchronized 關鍵字修飾或者使用類.class文件。
靜態的同步函數使用的鎖是該函數所屬字節碼文件對象
可以用 getClass方法獲取,也可以用當前類名.class 表示
public class SafeThread implements Runnable { private int ticketCount = 50; @Override public void run() { while (ticketCount > 0) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } // synchronized (this) { // System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); // ticketCount--; // } // sale(); sale2(); } } private synchronized void sale() { System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); ticketCount--; } private void sale2() { synchronized (SafeThread.class) { System.out.println(Thread.currentThread().getName() + ",出售第" + (50 - ticketCount + 1) + "張票"); ticketCount--; } } }死鎖問題
同步中嵌套同步,導致鎖無法釋放
解決辦法:盡量避免同步中嵌套同步
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74525.html
摘要:但是單核我們還是要應用多線程,就是為了防止阻塞。多線程可以防止這個問題,多條線程同時運行,哪怕一條線程的代碼執行讀取數據阻塞,也不會影響其它任務的執行。 1、多線程有什么用?一個可能在很多人看來很扯淡的一個問題:我會用多線程就好了,還管它有什么用?在我看來,這個回答更扯淡。所謂知其然知其所以然,會用只是知其然,為什么用才是知其所以然,只有達到知其然知其所以然的程度才可以說是把一個知識點...
摘要:是需要我們去處理很多事情,為了防止多線程給我們帶來的安全和性能的問題下面就來簡單總結一下我們需要哪些知識點來解決多線程遇到的問題。 前言 不小心就鴿了幾天沒有更新了,這個星期回家咯。在學校的日子要努力一點才行! 只有光頭才能變強 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 本文章的知識主要參考《Java并發編程實戰》這本書的前4章,這本書的前4章都是講解并發的基...
摘要:多線程環境下的一些問題安全性問題在沒有正確同步的情況下,多線程環境下程序可能得出錯誤的結果。一些相關概念競爭條件多線程的環境下,程序執行的結果取決于線程交替執行的方式。而線程的交替操作順序是不可預測的,如此程序執行的結果也是不可預測的。 入口 Java多線程的應用復雜性之如jvm有限的幾個內存方面的操作和規范,就像無數紛繁復雜的應用邏輯建立在有限的指令集上。 如何寫出線程安全的程序,有...
摘要:的內置鎖是一種互斥鎖,意味著最多只有一個線程能持有這種鎖。使用方式如下使用顯示鎖之前,解決多線程共享對象訪問的機制只有和。后面會陸續的補充并發編程系列的文章。 早期的計算機不包含操作系統,它們從頭到尾執行一個程序,這個程序可以訪問計算機中的所有資源。在這種情況下,每次都只能運行一個程序,對于昂貴的計算機資源來說是一種嚴重的浪費。 操作系統出現后,計算機可以運行多個程序,不同的程序在單獨...
摘要:程序正常運行,輸出了預期容量的大小這是正常運行結果,未發生多線程安全問題,但這是不確定性的,不是每次都會達到正常預期的。另外,像等都有類似多線程安全問題,在多線程并發環境下避免使用這種集合。 這個問題是 Java 程序員面試經常會遇到的吧。 工作一兩年的應該都知道 ArrayList 是線程不安全的,要使用線程安全的就使用 Vector,這也是各種 Java 面試寶典里面所提及的,可能...
摘要:下面是線程相關的熱門面試題,你可以用它來好好準備面試。線程安全問題都是由全局變量及靜態變量引起的。持有自旋鎖的線程在之前應該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網上流傳著,各種面試經驗及面試題,往往都是一大堆技術題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關線程的問題。Java語言一個重要的特點就是內置了對并發的支持,讓Java大受企業和程序員...
閱讀 3061·2021-10-27 14:16
閱讀 2879·2021-09-24 10:33
閱讀 2285·2021-09-23 11:21
閱讀 3229·2021-09-22 15:14
閱讀 812·2019-08-30 15:55
閱讀 1676·2019-08-30 15:53
閱讀 1742·2019-08-29 11:14
閱讀 2190·2019-08-28 18:11