線程同步的五種方式

java容許多線程併發控制,當多個線程同時操做一個可共享的資源變量時,將會致使數據不許確,相互之間產生衝突,所以加入同步鎖以免該線程沒有完成操做以前,被其餘線程調用,從而保證數據的惟一性和準確性。 1.同步方法,即爲synchronized關鍵字修飾的方法。 public sunchronized void save(){} 例如該方法,因爲java的每個內置對象都有一個內置鎖,當用此關鍵字修飾方法是,內置鎖會保護整個方法。在調用該方法前,須要得到內置鎖,不然就處於阻塞狀態。 注意:synchronized關鍵字也能夠修飾靜態方法,此時若是調用靜態方法,將會鎖住整個類。java

2.同步代碼塊,被關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步 synchronized(object){} 同步代碼塊和同步方法不一樣,同步代碼塊必須有鎖。 注意:同步是一種高開銷的操做,所以應該儘可能減小同步的內筒,一般咱們優先選擇同步代碼塊來同步關鍵代碼便可。面試

3.使用volatile關鍵字修飾變量來實現線程同步多線程

peivate volatile int account = 100; a.volatile關鍵字爲域變量的訪問提供了一種免鎖機制 b.使用volatile修飾域至關於告訴虛擬機該域有可能會被其餘線程更新,所以每次使用該域就要從新計算,而不是使用寄存器中的值。volatitle不會提供任何原子操做,他也不能用來修飾final類型的變量。併發

4.使用重入鎖實現線程同步 ReentrantLock類能夠重入,互斥,實現了Lock接口的鎖, 該類的經常使用方法 lock() 得到鎖 unlock(): 釋放鎖ide

class Bank {

            

            private int account = 100;

            //須要聲明這個鎖

            private Lock lock = new ReentrantLock();

            public int getAccount() {

                return account;

            }

            //這裏再也不須要synchronized 

            public void save(int money) {

                lock.lock();

                try{

                    account += money;

                }finally{

                    lock.unlock();

                }

                

            }

        }

注:關於Lock對象和synchronized關鍵字的選擇:線程

a.最好兩個都不用,使用一種java.util.concurrent包提供的機制, 

        可以幫助用戶處理全部與鎖相關的代碼。 

    b.若是synchronized關鍵字能知足用戶的需求,就用synchronized,由於它能簡化代碼 

    c.若是須要更高級的功能,就用ReentrantLock類,此時要注意及時釋放鎖,不然會出現死鎖,一般在finally代碼釋放鎖

5.使用局部變量實現線程同步 若是使用ThreadLocal管理變量,則每個人使用該變量的線程都得到該變量的副本。 副本之間相互獨立,這樣每個線程均可以隨意修改本身的變量副本,而不會對其餘線程產生影響。 ThreadLocal 類的經常使用方法 ThreadLocal() : 建立一個線程本地變量code

get() : 返回此線程局部變量的當前線程副本中的值 

initialValue() : 返回此線程局部變量的當前線程的"初始值" 

set(T value) : 將此線程局部變量的當前線程副本中的值設置爲value
public class Bank{

            //使用ThreadLocal類管理共享變量account

            private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){

                @Override

                protected Integer initialValue(){

                    return 100;

                }

            };

            public void save(int money){

                account.set(account.get()+money);

            }

            public int getAccount(){

                return account.get();

            }

        }

面試題:一個線程進入對象的synchronized方法A以後,其餘線程是否能夠進去此對象的synchronized的方法B? 回答:不能夠,所對象沒有釋放,其餘線程不能進入方法B。對象

相關文章
相關標籤/搜索