中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解Java如何實現線程同步

發布時間:2020-07-18 16:51:59 來源:億速云 閱讀:112 作者:小豬 欄目:編程語言

小編這次要給大家分享的是詳解Java如何實現線程同步,文章內容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

一、概述

無論是什么語言,在多線程編程中,常常會遇到多個線同時操作程某個變量(讀/寫),如果讀/寫不同步,則會造成不符合預期的結果。

例如:線程A和線程B并發運行,都操作變量X,若線程A對變量X進行賦上一個新值,線程B仍然使用變量X之前的值,很明顯線程B使用的X不是我們想要的值了。

Java提供了三種機制,解決上述問題,實現線程同步:

同步代碼塊

synchronized(鎖對象){
	// 這里添加受保護的數據操作
}

同步方法

靜態同步方法:synchronized修飾的靜態方法,它的同步鎖是當前方法所在類的字節碼對象

public static synchronized void staticMethod(){
}

非靜態同步方法:synchronized修飾的非靜態方法,它的同步鎖即為this

public synchronize void method(){
}

鎖機制

// 以可重入鎖舉例
Lock lock = new ReentrantLock(/*fail*/);
// fail:
// true表示使用公平鎖,即線程等待拿到鎖的時間越久,越容易拿到鎖
// false表示使用非公平鎖,線程拿到鎖全靠運氣。。。cpu時間片輪到哪個線程,哪個線程就能獲取鎖
lock.lock();
// 這里添加受保護的數據操作
lock.unlock();

個人理解:其實無論哪種機制實現線程同步,本質上都是加鎖->操作數據->解鎖的過程。同步代碼塊是針對{}中,同步方法是針對整個方法。其ReentrantLock類提供的lock和unlock和C++的std::mutex提供lock和unlock類似

二、測試用例

詳解Java如何實現線程同步

同步代碼塊測試類

package base.synchronize;


public class SynchronizeBlock implements Runnable {
  private int num = 100;

  @Override
  public void run() {
    while (num > 1) {
      synchronized (this) {
        // 同步代碼塊,只有拿到鎖,才有cpu執行權
        System.out.println("Thread ID:" + Thread.currentThread().getId() + "---num:" + num);
        num--;
      }
    }
    System.out.println("Thread ID:" + Thread.currentThread().getId() + " exit");
  }
}

同步方法測試類

package base.synchronize;

public class SynchronizeMethod implements Runnable {
  private int num = 100;
  public static int staticNum = 100;
  boolean useStaticMethod;

  public SynchronizeMethod(boolean useStaticMethodToTest) {
    this.useStaticMethod = useStaticMethodToTest;
  }

  // 對于非靜態方法,同步鎖對象即this
  public synchronized void method() {
    System.out.println("Thread ID:" + Thread.currentThread().getId() + "---num:" + num);
    num--;
  }

  // 對于靜態方法,同步鎖對象是當前方法所在類的字節碼對象
  public synchronized static void staticMethod() {
    System.out.println("Static Method Thread ID:" + Thread.currentThread().getId() + "---num:" + staticNum);
    staticNum--;
  }

  @Override
  public void run() {
    if (useStaticMethod) { // 測試靜態同步方法
      while (staticNum > 1) {
        staticMethod();
      }
    }else{ // 測試非靜態同步方法
      while (num > 1){
        method();
      }
    }
    System.out.println("Thread ID:" + Thread.currentThread().getId() + " exit");
  }
}

ReentrantLock測試類

package base.synchronize;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SynchronizeLock implements Runnable {
  private Lock lock = null;
  private int num = 100;

  public SynchronizeLock(boolean fair){
    lock = new ReentrantLock(fair); // 可重入鎖
  }

  @Override
  public void run() {
    while (num > 1) {
      try {
        lock.lock();
        System.out.println("Thread ID:" + Thread.currentThread().getId() + "---num:" + num);
        num--;
      } catch (Exception e) {
        e.printStackTrace();
      }finally {
        lock.unlock();
      }
    }
    System.out.println("Thread ID:" + Thread.currentThread().getId() + " exit");
  }
}

測試三種機制的Demo

package base.synchronize;

public class Demo {
  public static void main(String[] args) {
    synchronizeBlockTest();   // 同步代碼塊
    synchronizeMethodTest();  // 同步非靜態方法
    synchronizeStaticMethodTest(); // 同步靜態方法
    synchronizeLockTest();  // 可重入鎖機制
  }

  public static void synchronizeBlockTest(){
    Runnable run = new SynchronizeBlock();
    for(int i = 0; i < 3; i++){
      new Thread(run).start();
    }
  }

  public static void synchronizeMethodTest(){
    Runnable run = new SynchronizeMethod(false);
    for(int i = 0; i < 3; i++){
      new Thread(run).start();
    }

  }
  public static void synchronizeStaticMethodTest() {
    Runnable run = new SynchronizeMethod(true);
    for(int i = 0; i < 3; i++){
      new Thread(run).start();
    }
  }


  public static void synchronizeLockTest(){
    Runnable run = new SynchronizeLock(false); // true:使用公平鎖 false:使用非公平鎖
    for(int i = 0; i < 3; i++){
      new Thread(run).start();
    }
  }
}

無論哪種機制,都得到預期的效果,打印100-0

看完這篇關于詳解Java如何實現線程同步的文章,如果覺得文章內容寫得不錯的話,可以把它分享出去給更多人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宜丰县| 蓬莱市| 凌云县| 万年县| 合阳县| 巴塘县| 双鸭山市| 土默特左旗| 淳安县| 涞水县| 壤塘县| 太仓市| 德昌县| 手机| 文安县| 府谷县| 金溪县| 叙永县| 宣威市| 改则县| 滦平县| 农安县| 平湖市| 信阳市| 响水县| 漯河市| 长岛县| 长兴县| 麻阳| 伊宁县| 剑川县| 宜丰县| 宿迁市| 新营市| 米脂县| 沂水县| 阿鲁科尔沁旗| 信阳市| 台东县| 乐陵市| 纳雍县|