如何解決線程不安全問題呢?

線程安全問題存在,必然會引起很多問題。那麼本節就來講講,如何解決線程安全問題呢?

1、synchronized

synchronized關鍵字,就是java用來控制線程同步的,比如上節的最後舉例中,在代碼中加入共享變量後,使用多線程調用時,會產生count數據產生偏差問題。

 

此關鍵字,一般是加在方法上的如:

public static int count =0;

    public static  void  main(String[] args){
        for (int i = 0; i <3 ; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(getcountNum(30));
                    System.out.println("count爲:"+count);
                   try{
                       Thread.sleep(1);
                   }catch (Exception e){
                       e.printStackTrace();
                   }
                }
            }).start();
        }
    }

    public static synchronized  int getcountNum(int j){
        int i =1;
        count++;
        j=j+3;
        return j;
    }

運行結果爲:

此方法就變成了一個線程安全的方法了。

首先synchronized鎖的是括號裏的對象,而不是代碼,其次,對於非靜態的synchronized方法,鎖的是對象本身也就是this。

當synchronized鎖住一個對象之後,別的線程如果想要獲取鎖對象,那麼就必須等這個線程執行完釋放鎖對象之後纔可以,否則一直處於等待狀態。

雖然加synchronized關鍵字,可以讓我們的線程變得安全,但是我們在用的時候,也要注意縮小synchronized的使用範圍,如果隨意使用時很影響程序的性能,別的對象想拿到鎖,結果你沒用鎖還一直把鎖佔用,這樣就有點浪費資源。

也就是說:1.非static方法,同步鎖是this。2.static方法,使用當前方法所在類的字節碼對象(Apple.class)是同步鎖

2、lock

       先來說說它跟synchronized有什麼區別吧,Lock是在Java1.6被引入進來的,Lock的引入讓鎖有了可操作性,什麼意思?就是我們在需要的時候去手動的獲取鎖和釋放鎖,甚至我們還可以中斷獲取以及超時獲取的同步特性,但是從使用上說Lock明顯沒有synchronized使用起來方便快捷。我們先來看下一般是如何使用的:

 public static  void  main(String[] args){

        for (int i = 0; i <3 ; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    getcountNum(Thread.currentThread(),30);
                   try{
                       Thread.sleep(1);
                   }catch (Exception e){
                       e.printStackTrace();
                   }
                }
            }).start();
        }
    }
  private static   Lock lock = new ReentrantLock();
    public static  int getcountNum(Thread a,int j){
        lock.lock();
         int i =1;
         count++;
        System.out.println("當前是線程:"+a.getName()+",count="+count);
         j=j+3;
         lock.unlock();

        return j;
    }

上次分享線程不安全的文章中,得到的count全是3,加上鎖後得到結果是:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章