欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)線程同步方法及原理詳解

 更新時間:2020年06月03日 09:10:58   作者:main(0)  
這篇文章主要介紹了Java實現(xiàn)線程同步方法及原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

一、概述

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

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

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

同步代碼塊

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

同步方法

靜態(tài)同步方法:synchronized修飾的靜態(tài)方法,它的同步鎖是當前方法所在類的字節(jié)碼對象

public static synchronized void staticMethod(){
}

非靜態(tài)同步方法:synchronized修飾的非靜態(tài)方法,它的同步鎖即為this

public synchronize void method(){
}

鎖機制

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

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

二、測試用例

同步代碼塊測試類

package base.synchronize;


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

  @Override
  public void run() {
    while (num > 1) {
      synchronized (this) {
        // 同步代碼塊,只有拿到鎖,才有cpu執(zhí)行權(quán)
        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;
  }

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

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

  @Override
  public void run() {
    if (useStaticMethod) { // 測試靜態(tài)同步方法
      while (staticNum > 1) {
        staticMethod();
      }
    }else{ // 測試非靜態(tài)同步方法
      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();  // 同步非靜態(tài)方法
    synchronizeStaticMethodTest(); // 同步靜態(tài)方法
    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();
    }
  }
}

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

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Response如何實現(xiàn)重定向

    Response如何實現(xiàn)重定向

    這篇文章主要介紹了Response如何實現(xiàn)重定向方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Tomcat服務(wù)無法啟動的問題的解決方法

    Tomcat服務(wù)無法啟動的問題的解決方法

    這篇文章主要介紹了Tomcat服務(wù)無法啟動的問題的解決方法,需要的朋友可以參考下
    2014-02-02
  • SpringBoot中的自定義starter詳解

    SpringBoot中的自定義starter詳解

    這篇文章主要介紹了SpringBoot中的自定義starter詳解,SpringBoot中的starter是一種非常重要的機制,能夠拋棄以前繁雜的配置,將其統(tǒng)一集成進starter,需要的朋友可以參考下
    2024-01-01
  • Java Junit單元測試實例詳解

    Java Junit單元測試實例詳解

    在本篇文章里小編給大家分享的是關(guān)于Java Junit單元測試的相關(guān)知識點內(nèi)容,有興趣的朋友們學習下。
    2019-11-11
  • 一道Java集合框架題 多種解題思路

    一道Java集合框架題 多種解題思路

    這篇文章主要介紹了一道Java集合框架題,多種解題思路,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Jenkins一鍵打包部署SpringBoot應(yīng)用

    Jenkins一鍵打包部署SpringBoot應(yīng)用

    本文主要介紹了Jenkins一鍵打包部署SpringBoot應(yīng)用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Eclipse創(chuàng)建JavaWeb工程的完整步驟記錄

    Eclipse創(chuàng)建JavaWeb工程的完整步驟記錄

    很多新手不知道Eclipse怎么創(chuàng)建Java Web項目,一起來看看吧,這篇文章主要給大家介紹了關(guān)于Eclipse創(chuàng)建JavaWeb工程的完整步驟,需要的朋友可以參考下
    2023-10-10
  • Java?GUI編程菜單組件實例詳解

    Java?GUI編程菜單組件實例詳解

    在實際開發(fā)中,除了主界面,還有一類比較重要的內(nèi)容就是菜單相關(guān)組件,可以通過菜單相關(guān)組件很方便的使用特定的功能,今天通過本文給大家介紹下Java?GUI編程菜單組件實例詳解,感興趣的朋友一起看看吧
    2022-04-04
  • Java中的構(gòu)造方法(構(gòu)造函數(shù))與普通方法區(qū)別及說明

    Java中的構(gòu)造方法(構(gòu)造函數(shù))與普通方法區(qū)別及說明

    這篇文章主要介紹了Java中的構(gòu)造方法(構(gòu)造函數(shù))與普通方法區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 2021年最新Redis面試題匯總(1)

    2021年最新Redis面試題匯總(1)

    在程序員面試過程中redis相關(guān)的知識是常被問到的話題。這篇文章主要介紹了幾道Redis面試題,整理一下分享給大家,感興趣的小伙伴們可以參考一下
    2021-07-07

最新評論