看多線程的相關書籍的時候,會常常閱讀到一個使用前景,就是銀行的取錢存錢操做。
假設咱們使用兩個線程來模擬取錢操做,模擬兩我的使用同一個帳戶併發取錢的問題,咱們都知道存款不可能爲負的,
可是每每併發操做的時候,可能就會致使系統出錯致使出現負的數字(假設一開始都是200元餘額,兩邊同時操做取出150,系統可能就會出錯)。
出現相似這種問題就是缺乏同步安全性,爲了解決這個問題,Java就增進了同步監視器來解決這個,也就是本文講的synchronized的做用。安全
synchronized是Java中的關鍵字。同步的意思,用在解決線程安全問題上。有添加在方法上,和直接修飾代碼塊。有種保護的做用,使用修飾以後,家門上了鎖,別人進不來。用synchronized修飾的方法只容許一個線程執行,其餘線程沒法進入該方法。(原子性操做),銀行使用該操做以後,就會變成一個排隊操做同樣,像前言的例子,就會變成一我的等另外一個操做取出150以後才能夠取錢,這樣就不會出現負的餘額。多線程
因此synchronized保護的是線程遭受破壞,必須按照容許的權限進行資源訪問。
記得synchronized關鍵字能夠修飾方法,能夠修飾代碼塊,但不能修飾構造函數、屬性等。併發
//long與double的操做不是原子的
//synchronized代碼塊 //obj對象即表示線程開始執行同步代碼塊以前,必須先得到對同步監視器的鎖定 //步驟:加鎖--修改--釋放鎖 synchronized (obj) { ... }
任什麼時候刻只能有一個線程能夠得到對同步監視器的鎖定,當同步代碼塊執行完成後,該線程會釋放對該同步監視器的鎖定。具體的格式參見上面。函數
//synchronized方法,能夠分爲靜態方法和普通方法 synchronized void method(){ ... } //等價於 public void method() { synchronized(this) { // todo } } //不管哪一種形式均可以看作是「{」處獲取鎖,「}」釋放鎖
與同步代碼塊對應,Java 的多線程安全支持還提供了同步方法,同步方法就是使用synchronized關鍵字來修飾某個方法(放在權限詞的後面便可),則該方法稱爲同步方法。對於同步方法而言,無須顯式指定同步監視器,同步方法的同步監視器是this,也就是該對象自己。在格式上能夠看到一些用法,可是具體來說,synchronized用在方法體上還分爲用在普通方法和靜態方法兩種,區別在做用鎖對象的不一樣。工具
修飾普通方法做用的是調用這個方法的對象,修飾靜態方法做用是調用這個類的全部對象。 synchronized static方法能夠在類的範圍內防止對static數據的併發訪問,
使用同步方法能夠很方便得實現線程安全的類,這樣類的對象能夠被多個線程同時安全得訪問。學習
關於什麼使用同步,也就是上鎖,引用書上的話this
若是你在寫一個變量,它可能接下來將被另外一個線程讀取,或者正在讀取上一個已經被另外一個線程寫過的變量,那麼你必須使用同步,而且,讀取線程都必須用相同的監視器鎖同步線程
——Brain Goetz《Java Concurrency in Pactice》的做者code
我的學習記錄,有錯誤歡迎指點,謝謝!加油!