并发编程之Synchronized
在介紹Synchrinized之前,我們先來了解一下并發的相關概念。
什么是并發?
并發: 同一時間段,多個任務都在執行 (單位時間內不一定同時執行);在同一時刻只會有一條指令執行,但是多個指令被快速輪換執行,這個切換的時間非常短以至于我們不用去考慮它,這就是并發的基本含義。
而多線程正是我們可以完成并發的很重要的執行手段。現在的系統動不動就要求百萬級的并發量,而多線程并發編程正是開發高并發系統的基礎,利用好多線程的特性可以大大的提高我們的系統運行的效率。而且當今正值多核CPU時代,多線程也可以提高我們CPU的利用效率,最大化的利用我們現有的資源。
上文說了多線程這么多的好處,那么它有什么缺點呢?
我們在多線程的環境下,系統的執行順序并不是由我們控制的,執行的線程就可能隨時切換到其他線程中執行。這就可能會造成一些安全性的問題。 比如小A小B兩個人同時在搶票(僅剩一張),小A買票的線程先執行,判斷?num?是否大于0(現在?num?=1),然后?num--。執行完這個操作之后,小B線程也開始執行,也開始判斷?num?是否大于0,因為小A更新的num尚未更新到主存中,小B的工作空間的?num?值還是大于1,所以也執行?num--。
這個時候問題就出現了,只有一張票,做了兩次?num--,最后num的值為-1系統就出現了錯誤。那么如何防止這種現象出現呢?這里我們就引入了?Synchronzied。
什么是Synchronzied?
Synchronized?關鍵字解決的是多個線程之間訪問資源的同步性,Synchronized?關鍵字可以保證被它修飾的方法或者代碼塊在任意時刻只能有一個線程執行。
還用剛才的買票問題舉例,下面是代碼
while (true) {synchronized (obj) {if (ticket > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + ticket--);}}}復制代碼這次我們使用了?Synchronized?來對整個?if?語句進行修飾,就保證了if語句的原子性,只有當整個?if?語句的代碼執行完畢的時候,才會釋放鎖,我們也就很容易的解決了買票的問題。
下面我們來介紹一下?Synchronzied?的主要使用方式
synchronized?關鍵字最主要的三種使用方式:
* 修飾實例方法: 作用于當前對象實例加鎖,進入同步代碼前要獲得當前對象實例的鎖
* 修飾靜態方法: 也就是給當前類加鎖,會作用于類的所有對象實例,因為靜態成員不屬于任何一個實例對象,是類成員( static表明這是該類的一個靜態資源,不管new了多少個對象,只有一份)。所以如果一個線程A調用一個實例對象的非靜態 synchronized 方法,而線程B需要調用這個實例對象所屬類的靜態 synchronized 方法,是允許的,不會發生互斥現象,因為訪問靜態 synchronized 方法占用的鎖是當前類的鎖,而訪問非靜態 synchronized 方法占用的鎖是當前實例對象鎖。
* 修飾代碼塊: 指定加鎖對象,對給定對象加鎖,進入同步代碼庫前要獲得給定對象的鎖。
這些就是今天介紹?Synchronized?的全部內容,今后我也會持續在我的專欄中更新更多有價值的內容,歡迎關注。
轉載于:https://juejin.im/post/5ced2ccf6fb9a07ed2244ecf
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的并发编程之Synchronized的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基础关1
- 下一篇: celery开发中踩的坑