最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java使用synchronized修飾方法來(lái)同步線程的實(shí)例演示

 更新時(shí)間:2016年06月15日 15:16:44   作者:柳哥  
synchronized下的方法控制多線程程序中的線程同步非常方便,這里就來(lái)看一下Java使用synchronized修飾方法來(lái)同步線程的實(shí)例演示,需要的朋友可以參考下

Java中可以使用關(guān)鍵字synchronized進(jìn)行線程同步控制,實(shí)現(xiàn)關(guān)鍵資源順序訪問,避免由于多線程并發(fā)執(zhí)行導(dǎo)致的數(shù)據(jù)不一致性等問題。synchronized的原理是對(duì)象監(jiān)視器(鎖),只有獲取到監(jiān)視器的線程才能繼續(xù)執(zhí)行,否則線程會(huì)等待獲取監(jiān)視器。Java中每個(gè)對(duì)象或者類都有一把鎖與之相關(guān)聯(lián),對(duì)于對(duì)象來(lái)說(shuō),監(jiān)視的是這個(gè)對(duì)象的實(shí)例變量,對(duì)于類來(lái)說(shuō),監(jiān)視的是類變量(一個(gè)類本身是類Class的對(duì)象,所以與類關(guān)聯(lián)的鎖也是對(duì)象鎖)。synchronized關(guān)鍵字使用方式有兩種:synchronized方法和synchronized塊。這兩種監(jiān)視區(qū)域都和一個(gè)引入對(duì)象相關(guān)聯(lián),當(dāng)?shù)竭_(dá)這個(gè)監(jiān)視區(qū)域時(shí),JVM就會(huì)鎖住這個(gè)引用對(duì)象,當(dāng)離開時(shí)會(huì)釋放這個(gè)引用對(duì)象上的鎖(有異常退出時(shí),JVM會(huì)釋放鎖)。對(duì)象鎖是JVM內(nèi)部機(jī)制,只需要編寫同步方法或者同步塊即可,操作監(jiān)視區(qū)域時(shí)JVM會(huì)自動(dòng)獲取鎖或者釋放鎖。

示例1

先來(lái)看第一個(gè)示例,在java中,同一個(gè)對(duì)象的臨界區(qū),在同一時(shí)間只有一個(gè)允許被訪問(都是非靜態(tài)的synchronized方法):

package concurrency;

public class Main8 {
  public static void main(String[] args) {
    Account account = new Account();
    account.setBalance(1000);
    Company company = new Company(account);
    Thread companyThread = new Thread(company);
    Bank bank = new Bank(account);
    Thread bankThread = new Thread(bank);
    System.out.printf("Account : Initial Balance: %f\n", account.getBalance());
    companyThread.start();
    bankThread.start();
    try {
      //join()方法等待這兩個(gè)線程運(yùn)行完成
      companyThread.join();
      bankThread.join();
      System.out.printf("Account : Final Balance: %f\n", account.getBalance());
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

/*帳戶*/
class Account{
  private double balance;
  /*將傳入的數(shù)據(jù)加到余額balance中*/
  public synchronized void addAmount(double amount){
    double tmp = balance;
    try {
      Thread.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    tmp += amount;
    balance = tmp;
  }
  /*將傳入的數(shù)據(jù)從余額balance中扣除*/
  public synchronized void subtractAmount(double amount){
    double tmp = balance;
    try {
      Thread.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    tmp -= amount;
    balance = tmp;
  }
  public double getBalance() {
    return balance;
  }
  public void setBalance(double balance) {
    this.balance = balance;
  }
}

/*銀行*/
class Bank implements Runnable{
  private Account account;
  public Bank(Account account){
    this.account = account;
  }
  @Override
  public void run() {
    for (int i = 0; i < 100; i++) {
      account.subtractAmount(1000);
    }
  }
}

/*公司*/
class Company implements Runnable{
  private Account account;
  public Company(Account account){
    this.account = account;
  }
  @Override
  public void run() {
    for (int i = 0; i < 100; i++) {
      account.addAmount(1000);
    }
  }
}

你已經(jīng)開發(fā)了一個(gè)銀行賬戶的模擬應(yīng)用,它能夠?qū)τ囝~進(jìn)行充值和扣除。這個(gè)程序通過(guò)調(diào)用100次addAmount()方法對(duì)帳戶進(jìn)行充值,每次存入1000;然后通過(guò)調(diào)用100次subtractAmount()方法對(duì)帳戶余額進(jìn)行扣除,每次扣除1000;我們期望帳戶的最終余額與起初余額相等,我們通過(guò)synchronized關(guān)鍵字實(shí)現(xiàn)了。

如果想查看共享數(shù)據(jù)的并發(fā)訪問問題,只需要將addAmount()和subtractAmount()方法聲明中的synchronized關(guān)鍵字刪除即可。在沒有synchronized關(guān)鍵字的情況下,打印出來(lái)的余額值并不一致。如果多次運(yùn)行這個(gè)程序,你將獲取不同的結(jié)果。因?yàn)镴VM并不保證線程的執(zhí)行順序,所以每次運(yùn)行的時(shí)候,線程將以不同的順序讀取并且修改帳戶的余額,造成最終結(jié)果也是不一樣的。

一個(gè)對(duì)象的方法采用synchronized關(guān)鍵字進(jìn)行聲明,只能被一個(gè)線程訪問。如果線程A正在執(zhí)行一個(gè)同步方法syncMethodA(),線程B要執(zhí)行這個(gè)對(duì)象的其他同步方法syncMethodB(),線程B將被阻塞直到線程A訪問完。但如果線程B訪問的是同一個(gè)類的不同對(duì)象,那么兩個(gè)線程都不會(huì)被阻塞。

示例2

演示同一個(gè)對(duì)象上的靜態(tài)synchronized方法與非靜態(tài)synchronized方法可以在同一時(shí)間點(diǎn)被多個(gè)線程訪問的問題,驗(yàn)證一下。

package concurrency;

public class Main8 {
  public static void main(String[] args) {
    Account account = new Account();
    account.setBalance(1000);
    Company company = new Company(account);
    Thread companyThread = new Thread(company);
    Bank bank = new Bank(account);
    Thread bankThread = new Thread(bank);
    System.out.printf("Account : Initial Balance: %f\n", account.getBalance());
    companyThread.start();
    bankThread.start();
    try {
      //join()方法等待這兩個(gè)線程運(yùn)行完成
      companyThread.join();
      bankThread.join();
      System.out.printf("Account : Final Balance: %f\n", account.getBalance());
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

/*帳戶*/
class Account{
  /*這里改為靜態(tài)變量*/
  private static double balance = 0;
  /*將傳入的數(shù)據(jù)加到余額balance中,注意是用static修飾過(guò)的*/
  public static synchronized void addAmount(double amount){
    double tmp = balance;
    try {
      Thread.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    tmp += amount;
    balance = tmp;
  }
  /*將傳入的數(shù)據(jù)從余額balance中扣除*/
  public synchronized void subtractAmount(double amount){
    double tmp = balance;
    try {
      Thread.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    tmp -= amount;
    balance = tmp;
  }
  public double getBalance() {
    return balance;
  }
  public void setBalance(double balance) {
    this.balance = balance;
  }
}

/*銀行*/
class Bank implements Runnable{
  private Account account;
  public Bank(Account account){
    this.account = account;
  }
  @Override
  public void run() {
    for (int i = 0; i < 100; i++) {
      account.subtractAmount(1000);
    }
  }
}

/*公司*/
class Company implements Runnable{
  private Account account;
  public Company(Account account){
    this.account = account;
  }
  @Override
  public void run() {
    for (int i = 0; i < 100; i++) {
      account.addAmount(1000);
    }
  }
}

我只是把上個(gè)例子中的,balance加了static關(guān)鍵字修改,addAmount()方法也可以static關(guān)鍵字修飾。執(zhí)行結(jié)果大家可以自己測(cè)試一下,每次執(zhí)行都是不一樣的結(jié)果!

一些總結(jié):

  • synchronized是通過(guò)軟件(JVM)實(shí)現(xiàn)的,簡(jiǎn)單易用,即使在JDK5之后有了Lock,仍然被廣泛地使用。
  • synchronized實(shí)際上是非公平的,新來(lái)的線程有可能立即獲得監(jiān)視器,而在等待區(qū)中等候已久的線程可能再次等待,不過(guò)這種搶占的方式可以預(yù)防饑餓。
  • synchronized只有鎖只與一個(gè)條件(是否獲取鎖)相關(guān)聯(lián),不靈活,后來(lái)Condition與Lock的結(jié)合解決了這個(gè)問題。
  • 多線程競(jìng)爭(zhēng)一個(gè)鎖時(shí),其余未得到鎖的線程只能不停的嘗試獲得鎖,而不能中斷。高并發(fā)的情況下會(huì)導(dǎo)致性能下降。ReentrantLock的lockInterruptibly()方法可以優(yōu)先考慮響應(yīng)中斷。 一個(gè)線程等待時(shí)間過(guò)長(zhǎng),它可以中斷自己,然后ReentrantLock響應(yīng)這個(gè)中斷,不再讓這個(gè)線程繼續(xù)等待。有了這個(gè)機(jī)制,使用ReentrantLock時(shí)就不會(huì)像synchronized那樣產(chǎn)生死鎖了。

相關(guān)文章

  • Java輸出打印工具類封裝的實(shí)例

    Java輸出打印工具類封裝的實(shí)例

    下面小編就為大家?guī)?lái)一篇Java輸出打印工具類封裝的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Java?工具類實(shí)現(xiàn)音頻音量提升

    Java?工具類實(shí)現(xiàn)音頻音量提升

    本文主要介紹了可以將音頻提升音量的一個(gè)java工具類示例代碼,代碼具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴來(lái)了解一下吧,,希望能夠給你帶來(lái)幫助
    2021-11-11
  • 使用synchronized關(guān)鍵字實(shí)現(xiàn)信號(hào)量的方法

    使用synchronized關(guān)鍵字實(shí)現(xiàn)信號(hào)量的方法

    在Java中,信號(hào)量(Semaphore)是一種常用的同步工具,它可以用來(lái)控制對(duì)共享資源的訪問數(shù)量,下面,我們將使用Synchronized關(guān)鍵字來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的信號(hào)量,我們的目標(biāo)是實(shí)現(xiàn)一個(gè)計(jì)數(shù)信號(hào)量,其中信號(hào)量的計(jì)數(shù)指示可以同時(shí)訪問某一資源的線程數(shù),需要的朋友可以參考下
    2024-04-04
  • java基于AspectJ(面向切面編程)編碼示例分享

    java基于AspectJ(面向切面編程)編碼示例分享

    AspectJ是一種面向切面程序設(shè)計(jì)的基于Java的實(shí)現(xiàn),下面對(duì)過(guò)示例學(xué)習(xí)他的使用方法,需要的朋友可以參考下
    2014-02-02
  • java中DecimalFormat四舍五入用法詳解

    java中DecimalFormat四舍五入用法詳解

    這篇文章主要為大家詳細(xì)介紹了java中DecimalFormat四舍五入的用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • eclipse中自動(dòng)生成構(gòu)造函數(shù)的兩種方法

    eclipse中自動(dòng)生成構(gòu)造函數(shù)的兩種方法

    下面小編就為大家?guī)?lái)一篇eclipse中自動(dòng)生成構(gòu)造函數(shù)的兩種方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • profiles.active多環(huán)境開發(fā)、測(cè)試、部署過(guò)程

    profiles.active多環(huán)境開發(fā)、測(cè)試、部署過(guò)程

    這篇文章主要介紹了profiles.active多環(huán)境開發(fā)、測(cè)試、部署,主要講如何使用profiles.active這個(gè)變量,讓我們?cè)陂_發(fā)過(guò)程快速切換環(huán)境配置,以及如何使一個(gè)部署適配各種不同的環(huán)境,需要的朋友可以參考下
    2023-03-03
  • SpringBoot實(shí)現(xiàn)PPT格式文件上傳并在線預(yù)覽功能

    SpringBoot實(shí)現(xiàn)PPT格式文件上傳并在線預(yù)覽功能

    本文介紹SpringBoot實(shí)現(xiàn)PPT格式文件上傳并在線預(yù)覽功能,通過(guò)上傳接口,可在C盤的tempfile目錄下找到上傳的文件,預(yù)覽時(shí)會(huì)在同級(jí)目錄下創(chuàng)建一個(gè)相同文件名后綴為pdf的文件,每次預(yù)覽會(huì)先查找文件是否存在,存在則直接預(yù)覽,不存在則會(huì)走上面的處理,需要的朋友可以參考下
    2022-02-02
  • Java隊(duì)列同步器之CountDownLatch實(shí)現(xiàn)詳解

    Java隊(duì)列同步器之CountDownLatch實(shí)現(xiàn)詳解

    這篇文章主要介紹了Java隊(duì)列同步器之CountDownLatch實(shí)現(xiàn)詳解,CountDownLatch是一個(gè)同步工具類,它允許一個(gè)或多個(gè)線程一直等待,直到其他線程執(zhí)行完后再執(zhí)行,例如,應(yīng)用程序的主線程希望在負(fù)責(zé)啟動(dòng)框架服務(wù)的線程已經(jīng)啟動(dòng)所有框架服務(wù)之后執(zhí)行,需要的朋友可以參考下
    2023-12-12
  • Java中的CyclicBarrier同步屏障詳解

    Java中的CyclicBarrier同步屏障詳解

    這篇文章主要介紹了Java中的CyclicBarrier同步屏障詳解,CyclicBarrier也叫同步屏障,在JDK1.5被引入,可以讓一組線程達(dá)到一個(gè)屏障時(shí)被阻塞,直到最后一個(gè)線程達(dá)到屏障時(shí),屏障才會(huì)開門,所有被阻塞的線程才會(huì)繼續(xù)執(zhí)行,需要的朋友可以參考下
    2023-09-09

最新評(píng)論

郴州市| 马山县| 清水县| 海林市| 安新县| 南涧| 博爱县| 辉南县| 溆浦县| 怀来县| 临安市| 太和县| 榆林市| 长汀县| 桂阳县| 武隆县| 中阳县| 明溪县| 余姚市| 汉川市| 隆安县| 乐山市| 孝义市| 浮山县| 新竹县| 尼玛县| 阿图什市| 平原县| 池州市| 穆棱市| 汉沽区| 太保市| 象州县| 沙坪坝区| 华池县| 宁乡县| 华蓥市| 神木县| 伊春市| 陆良县| 贡山|