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

Java Synchronized的使用詳解

 更新時(shí)間:2020年07月16日 10:17:10   作者:淘小笛  
這篇文章主要介紹了Java Synchronized的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1.為什么要使用synchronized

在并發(fā)編程中存在線程安全問(wèn)題,主要原因有:1.存在共享數(shù)據(jù) 2.多線程共同操作共享數(shù)據(jù)。關(guān)鍵字synchronized可以保證在同一時(shí)刻,只有一個(gè)線程可以執(zhí)行某個(gè)方法或某個(gè)代碼塊,同時(shí)synchronized可以保證一個(gè)線程的變化可見(jiàn)(可見(jiàn)性),即可以代替volatile。

2.實(shí)現(xiàn)原理

synchronized可以保證方法或者代碼塊在運(yùn)行時(shí),同一時(shí)刻只有一個(gè)方法可以進(jìn)入到臨界區(qū),同時(shí)它還可以保證共享變量的內(nèi)存可見(jiàn)性

3.synchronized的三種應(yīng)用方式

Java中每一個(gè)對(duì)象都可以作為鎖,這是synchronized實(shí)現(xiàn)同步的基礎(chǔ):

普通同步方法(實(shí)例方法),鎖是當(dāng)前實(shí)例對(duì)象 ,進(jìn)入同步代碼前要獲得當(dāng)前實(shí)例的鎖靜態(tài)同步方法,鎖是當(dāng)前類的class對(duì)象 ,進(jìn)入同步代碼前要獲得當(dāng)前類對(duì)象的鎖同步方法塊,鎖是括號(hào)里面的對(duì)象,對(duì)給定對(duì)象加鎖,進(jìn)入同步代碼庫(kù)前要獲得給定對(duì)象的鎖。

4.synchronized的作用

Synchronized是Java中解決并發(fā)問(wèn)題的一種最常用最簡(jiǎn)單的方法 ,他可以確保線程互斥的訪問(wèn)同步代碼

5.舉栗子

**一、synchronized作用于實(shí)例方法**

①多個(gè)線程訪問(wèn)同一個(gè)對(duì)象的同一個(gè)方法

public class synchronizedTest implements Runnable {
  //共享資源
  static int i =0;
  /**
   * synchronized 修飾實(shí)例方法
   */
  public synchronized void increase(){
    i++;
  }
  @Override
  public void run(){
    for (int j =0 ; j<10000;j++){
      increase();
    }
  }

  public static void main(String[] args) throws InterruptedException {
    synchronizedTest test = new synchronizedTest();
    Thread t1 = new Thread(test);
    Thread t2 = new Thread(test);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(i);
  }
}

結(jié)果:


分析:當(dāng)兩個(gè)線程同時(shí)對(duì)一個(gè)對(duì)象的一個(gè)方法進(jìn)行操作,只有一個(gè)線程能夠搶到鎖。因?yàn)橐粋€(gè)對(duì)象只有一把鎖,一個(gè)線程獲取了該對(duì)象的鎖之后,其他線程無(wú)法獲取該對(duì)象的鎖,就不能訪問(wèn)該對(duì)象的其他synchronized實(shí)例方法,但是可以訪問(wèn)非synchronized修飾的方法

②一個(gè)線程獲取了該對(duì)象的鎖之后,其他線程來(lái)訪問(wèn)其他synchronized實(shí)例方法現(xiàn)象 舉栗

public class SynchronizedTest {
  public synchronized void method1() {
    System.out.println("Method 1 start");
    try {
      System.out.println("Method 1 execute");
      Thread.sleep(3000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Method 1 end");
  }

  public synchronized void method2() {
    System.out.println("Method 2 start");
    try {
      System.out.println("Method 2 execute");
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Method 2 end");
  }


  public static void main(String[] args) {
    final SynchronizedTest test = new SynchronizedTest();

    new Thread(test::method1).start();

    new Thread(test::method2).start();
  }

}

結(jié)果:


分析:可以看出其他線程來(lái)訪問(wèn)synchronized修飾的其他方法時(shí)需要等待線程1先把鎖釋放

③一個(gè)線程獲取了該對(duì)象的鎖之后,其他線程來(lái)訪問(wèn)其他非synchronized實(shí)例方法現(xiàn)象 舉栗
去掉②中方法二的synchronized

public class SynchronizedTest {
  public synchronized void method1() {
    System.out.println("Method 1 start");
    try {
      System.out.println("Method 1 execute");
      Thread.sleep(3000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Method 1 end");
  }

  public void method2() {
    System.out.println("Method 2 start");
    try {
      System.out.println("Method 2 execute");
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Method 2 end");
  }


  public static void main(String[] args) {
    final SynchronizedTest test = new SynchronizedTest();

    new Thread(test::method1).start();
    new Thread(test::method2).start();
  }

}

結(jié)果:


分析:當(dāng)線程1還在執(zhí)行時(shí),線程2也執(zhí)行了,所以當(dāng)其他線程來(lái)訪問(wèn)非synchronized修飾的方法時(shí)是可以訪問(wèn)的

④當(dāng)多個(gè)線程作用于不同的對(duì)象

public class SynchronizedTest {
  public synchronized void method1() {
    System.out.println("Method 1 start");
    try {
      System.out.println("Method 1 execute");
      Thread.sleep(3000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Method 1 end");
  }

  public synchronized void method2() {
    System.out.println("Method 2 start");
    try {
      System.out.println("Method 2 execute");
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Method 2 end");
  }


  public static void main(String[] args) {
    final SynchronizedTest test1 = new SynchronizedTest();
    final SynchronizedTest test2 = new SynchronizedTest();

    new Thread(test1::method1).start();

    new Thread(test2::method2).start();
  }

}

結(jié)果:


分析:因?yàn)閮蓚€(gè)線程作用于不同的對(duì)象,獲得的是不同的鎖,所以互相并不影響

**此處思考一個(gè)問(wèn)題:為什么分布式環(huán)境下synchronized失效?如何解決這種情況?

****二、synchronized作用于靜態(tài)方法**

public class synchronizedTest implements Runnable {
  //共享資源
  static int i =0;
  /**
   * synchronized 修飾實(shí)例方法
   */
  public static synchronized void increase(){
    i++;
  }
  @Override
  public void run(){
    for (int j =0 ; j<10000;j++){
      increase();
    }
  }

  public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(new synchronizedTest());
    Thread t2 = new Thread(new synchronizedTest());
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(i);
  }

結(jié)果:


分析:由例子可知,兩個(gè)線程實(shí)例化兩個(gè)不同的對(duì)象,但是訪問(wèn)的方法是靜態(tài)的,兩個(gè)線程發(fā)生了互斥(即一個(gè)線程訪問(wèn),另一個(gè)線程只能等著),因?yàn)殪o態(tài)方法是依附于類而不是對(duì)象的,當(dāng)synchronized修飾靜態(tài)方法時(shí),鎖是class對(duì)象。

**三、synchronized作用于同步代碼塊**

為什么要同步代碼塊呢?在某些情況下,我們編寫的方法體可能比較大,同時(shí)存在一些比較耗時(shí)的操作,而需要同步的代碼又只有一小部分,如果直接對(duì)整個(gè)方法進(jìn)行同步操作,可能會(huì)得不償失,此時(shí)我們可以使用同步代碼塊的方式對(duì)需要同步的代碼進(jìn)行包裹,這樣就無(wú)需對(duì)整個(gè)方法進(jìn)行同步操作了。

public class synchronizedTest implements Runnable {
  static synchronizedTest instance=new synchronizedTest();
  static int i=0;
  @Override
  public void run() {
    //省略其他耗時(shí)操作....
    //使用同步代碼塊對(duì)變量i進(jìn)行同步操作,鎖對(duì)象為instance
    synchronized(instance){
      for(int j=0;j<10000;j++){
        i++;
      }
    }
  }
  public static void main(String[] args) throws InterruptedException {
    Thread t1=new Thread(instance);
    Thread t2=new Thread(instance);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(i);
  }
}

結(jié)果:


分析:將synchronized作用于一個(gè)給定的實(shí)例對(duì)象instance,即當(dāng)前實(shí)例對(duì)象就是鎖對(duì)象,每次當(dāng)線程進(jìn)入synchronized包裹的代碼塊時(shí)就會(huì)要求當(dāng)前線程持有instance實(shí)例對(duì)象鎖,如果當(dāng)前有其他線程正持有該對(duì)象鎖,那么新到的線程就必須等待,這樣也就保證了每次只有一個(gè)線程執(zhí)行i++;操作。當(dāng)然除了instance作為對(duì)象外,我們還可以使用this對(duì)象(代表當(dāng)前實(shí)例)或者當(dāng)前類的class對(duì)象作為鎖,如下代碼:

//this,當(dāng)前實(shí)例對(duì)象鎖
synchronized(this){
  for(int j=0;j<1000000;j++){
    i++;
  }
}

//class對(duì)象鎖
synchronized(AccountingSync.class){
  for(int j=0;j<1000000;j++){
    i++;
  }
}

下一篇將深入介紹Synchronized的實(shí)現(xiàn)原理

到此這篇關(guān)于Java Synchronized的使用詳解的文章就介紹到這了,更多相關(guān)Java Synchronized使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析

    Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析

    這篇文章介紹了Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • 深入解析堆排序的算法思想及Java代碼的實(shí)現(xiàn)演示

    深入解析堆排序的算法思想及Java代碼的實(shí)現(xiàn)演示

    堆排序基于二叉堆結(jié)構(gòu)即完全二叉樹(shù),可利用最大堆和最小堆的組建方式來(lái)進(jìn)行排序,這里就來(lái)深入解析堆排序的算法思想及Java代碼的實(shí)現(xiàn)演示
    2016-06-06
  • Java中scheduleAtFixedRate的用法

    Java中scheduleAtFixedRate的用法

    如何正確使用Java中的scheduleAtFixedRate是一篇介紹Java中定時(shí)任務(wù)調(diào)度器的文章。它詳細(xì)介紹了scheduleAtFixedRate方法的用法、參數(shù)及作用,并給出了一些實(shí)例以幫助讀者更好地理解其使用。本文為Java開(kāi)發(fā)人員提供了一些實(shí)用的技巧,幫助他們更好地管理和控制定時(shí)任務(wù)
    2023-04-04
  • 詳解Java回環(huán)屏障CyclicBarrier

    詳解Java回環(huán)屏障CyclicBarrier

    這篇文章主要介紹了Java回環(huán)屏障CyclicBarrier的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-09-09
  • JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)原理解析

    JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)原理解析

    這篇文章主要介紹了JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • 詳解Java如何實(shí)現(xiàn)FP-Growth算法

    詳解Java如何實(shí)現(xiàn)FP-Growth算法

    學(xué)校里的實(shí)驗(yàn),要求實(shí)現(xiàn)FP-Growth算法.FP-Growth算法比Apriori算法快很多(但是卻比不上時(shí)間)在網(wǎng)上搜索后發(fā)現(xiàn)Java實(shí)現(xiàn)的FP-Growth算法很少,且大多數(shù)不太能理解):太菜.所以就自己實(shí)現(xiàn)了一下.這篇文章重點(diǎn)介紹一下我的Java實(shí)現(xiàn) ,需要的朋友可以參考下
    2021-06-06
  • Java Swing組件JFileChooser用法實(shí)例分析

    Java Swing組件JFileChooser用法實(shí)例分析

    這篇文章主要介紹了Java Swing組件JFileChooser用法,結(jié)合實(shí)例形式分析了java Swing組件JFileChooser文件選擇器的功能、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-11-11
  • 淺談線程通信wait,notify作用

    淺談線程通信wait,notify作用

    這篇文章主要介紹了淺談線程通信wait,notify作用,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-12-12
  • 詳解Java的橋接方法

    詳解Java的橋接方法

    這篇文章主要介紹了Java 橋接方法的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • 使用Stargate訪問(wèn)K8ssandra的過(guò)程之Springboot整合Cassandra

    使用Stargate訪問(wèn)K8ssandra的過(guò)程之Springboot整合Cassandra

    這篇文章主要介紹了使用Stargate訪問(wèn)K8ssandra的過(guò)程之Springboot整合Cassandra,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10

最新評(píng)論

新野县| 莱州市| 宝丰县| 杂多县| 顺义区| 台中市| 璧山县| 崇左市| 淮阳县| 鹤壁市| 库伦旗| 班玛县| 黄梅县| 怀远县| 海林市| 恭城| 贵港市| 锡林郭勒盟| 泾源县| 蕉岭县| 朝阳区| 抚州市| 太仓市| 西华县| 元江| 靖安县| 贺兰县| 斗六市| 象山县| 邻水| 渭南市| 柯坪县| 乐亭县| 宝清县| 虞城县| 达州市| 北碚区| 日土县| 璧山县| 黄石市| 雅安市|