激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - java多線程的同步方法實例代碼

java多線程的同步方法實例代碼

2020-09-19 18:24Java之家 JAVA教程

這篇文章主要介紹了 java多線程的同步方法實例代碼的相關資料,需要的朋友可以參考下

 java多線程的同步方法實例代碼

先看一個段有關銀行存錢的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Bank {
  private int sum;
  public void add(int num){
    sum = sum + num;
    try {
      Thread.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("total num is : " + sum);
  }
}
class Custom implements Runnable{
  private Bank b = new Bank();
 
  @Override
  public void run() {
    for(int i = 3 ; i > 0 ; i--)
      b.add(100);
  }
}
public class BankDemo{
  public static void main(String[] args) {
    Custom custom = new Custom();
    Thread t1 = new Thread(custom);
    Thread t2 = new Thread(custom);
    t1.start();
    t2.start();
  }
}

此代碼的運行結果為:

?
1
2
3
4
5
6
total num is : 100
total num is : 300
total num is : 400
total num is : 500
total num is : 500
total num is : 600

可以看出sum的值與預期的效果不太一樣;造成這種現象的原因有兩個:

1.程序存在兩個以上的子線程;

2.子線程中存在多條語句操作同一變量;

上述例子中:創建了兩個子線程·t1 和 t2,分別向銀行中存錢。但是可以看出銀行的實力隨著Custom的創建,只創建了一個對象。也就是說我們只操作一個數據變量即為銀行中錢的總數sum;當兩個子線程開啟的時候run方法中調用了bank的add方法,而add方法中有兩個語句都在操作sum一個sum的增加,一個是打印sum,當兩個子線程搶占cpu執行各自的程序的時候會出現:

當t1執行到add以后,t2搶到了cpu的執行權,執行也是執行了add語句,隨后打印出sum的值,這時候由于sum增加了兩次,所以打印出來的sum值為200。類推,假如這個時候t1又搶回了cpu的執行權,因此又打印出一次200。

顯然這種現象是我們不希望產生的。我們希望一個線程存完錢然后打印出結果,之后才允許下一次添加操作。這就是多線程會產生的問題,線程不安全。

我們應盡量避免這種現象的發生,Java給我們提供了三種方法來解決這個問題:

第一種:同步代碼塊

?
1
2
3
4
5
6
7
8
9
10
11
12
//private Object obj = new Object();
  public void add(int num) {
    synchronized (this) {
      sum = sum + num;
      try {
        Thread.sleep(10);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("total num is : " + sum);
    }
  }

將多線程中需要操作同一數據對象的語句使用同步代碼塊包含。同步代碼塊的原理就是:

1.java中每個對象都有一個內置鎖;

2.當程序運行到同步代碼塊的時候首先會獲取指定對象的鎖,這個鎖對于多個線程來說是唯一的。我們可以創建任意一個對象(obj)讓他當作同步代碼塊的鎖。

3.當程序中只有一個只有一個鎖的話我們還可以使用this,this代表當前執行代碼所操作的實例對象的鎖。即擁有add方法的類的對象,即bank。

4.兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。

這樣就可以操作同一個數據的多條語句只能在“同一段時間”只能被一個子線程所操作。

第二種 同步函數

?
1
2
3
4
5
6
7
8
9
public synchronized void add(int num) {
     sum = sum + num;
     try {
       Thread.sleep(10);
     } catch (InterruptedException e) {
       e.printStackTrace();
     }
     System.out.println("total num is : " + sum);
   }

除了同步代碼塊以外我們還可以將需要同步的操作抽象成一個函數,然后將這個函數用synchronized修飾,形成同步方法。比如上述例子中的add方法中的語句都在操作sum對象。我們就可以將add方法使用synchronized修飾。這樣也能達到代碼同步的效果。

同步方法使用的鎖其實就是 this。

值得一提的是:同步方法和同步代碼塊,在開發程序的時候我們更推薦使用同步代碼塊。

1.同步代碼塊可以綁定任意對象,而同步函數只能綁定該類對象this

2.如果多個線程使用同一個鎖的話,那么兩者均可以使用,如果存在多個鎖的(比如,在一個對象的同步方法里面調用另外一個對象的同步方法,則獲取了兩個對象的同步鎖),只能使用同步代碼塊。
靜態方法的同步
同步方法

?
1
public synchronized static void add(int num){}

同步代碼塊:

?
1
2
3
4
public synchronized void add(int num){
  synchronized (Bank.Class) {
  }
}

靜態方法的默認同步鎖是當前方法所在類的.class 對象,注意this與static不可以連用,所以不能使用this.Class

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美日韩手机在线观看 | 久久草在线视频免费 | 免费国产人成网站 | 玖玖精品视频在线 | 国产一区二区不卡视频 | 精品不卡| 日本精品一区二区 | 91成人影库 | 成人在线免费视频观看 | 污污短视频 | 日本a在线观看 | 欧美一级特黄特色大片免费 | 在线观看国产免费视频 | 中国女警察一级毛片视频 | 欧美精品一区二区三区久久久 | 国产人成精品综合欧美成人 | 亚洲成人精品久久 | 好吊一区二区三区 | 最新中文字幕第一页视频 | 国产亚洲精品久久久久婷婷瑜伽 | 最新黄色电影网站 | 日本成人在线免费 | 国产一级aaa全黄毛片 | 免费视频www在线观看 | 99久久精品免费视频 | 香蕉黄色网| 国产91对白叫床清晰播放 | 一级免费 | 女教师~淫辱の动漫在线 | 欧美一区2区三区4区公司二百 | 国产精品久久久在线观看 | 免费看搡女人无遮挡的视频 | 激情久久一区二区 | 国产精品免费久久久久 | 伊人亚洲精品 | 激情视频在线播放 | 手机国产乱子伦精品视频 | 精品国产一区二区三区成人影院 | 最新久久免费视频 | 国产在线精品一区二区三区不卡 | 在线亚洲播放 |