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

詳解Java多線程編程中的線程同步方法

 更新時間:2016年05月10日 08:59:48   作者:arthinking  
這篇文章主要介紹了Java多線程編程中的線程同步方法,使用synchronized關鍵字創(chuàng)建線程同步方法是實現(xiàn)線程同步的關鍵,需要的朋友可以參考下

1、多線程的同步:
1.1、同步機制:
在多線程中,可能有多個線程試圖訪問一個有限的資源,必須預防這種情況的發(fā)生。所以引入了同步機制:在線程使用一個資源時為其加鎖,這樣其他的線程便不能訪問那個資源了,直到解鎖后才可以訪問。

1.2、共享成員變量的例子:
成員變量與局部變量:
成員變量:

如果一個變量是成員變量,那么多個線程對同一個對象的成員變量進行操作,這多個線程是共享一個成員變量的。

局部變量:

如果一個變量是局部變量,那么多個線程對同一個對象進行操作,每個線程都會有一個該局部變量的拷貝。他們之間的局部變量互不影響。

下面舉例說明:
實現(xiàn)了Runnable的線程類:

class MyThread3 implements Runnable{

 //兩個線程操作同一個對象,共享成員變量
 //int i;
 @Override
 public void run() {
  //兩個線程操作同一個對象,各自保存局部變量的拷貝
  int i = 0;
  while(i<100){
   System.out.println(i);
   i++;
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}

在main方法中用兩個線程操作同一個對象:

public static void main(String[] args) {

 MyThread3 myThread = new MyThread3();
 //下面兩個線程對同一個對象(Runnable的實現(xiàn)類對象)進行操作
 Thread thread = new Thread(myThread);
 Thread thread2 = new Thread(myThread);
 //各自保存局部變量的拷貝,互不影響,輸出200個數(shù)字
 thread.start();
 thread2.start();
}

這里如果把i變成成員變量,則輸出100個數(shù)字。

1.3、共享資源導致的讀取錯誤
下面舉個例子,兩個線程共用一個Number對象,通過Number類的getNumber方法獲取數(shù)據(jù),讀取數(shù)據(jù)并改寫時,發(fā)現(xiàn)了重復讀操作:

首先創(chuàng)建一個Number類:

class Number{
 private int number = 10;
 public String getNumber(int i){
  if(number > 0){
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   number -= i;
   return "取出"+i+"成功,剩余數(shù)量:"+number;
  }
  return "取出"+i+"失敗,剩余數(shù)量:"+number;
 }
}

線程類,在線程類中的私有屬性包含了Number類的引用:

class MyThread4 extends Thread{

 //兩個線程操作同一個對象,共享成員變量
 Number number;
 public MyThread4(Number number){
  this.number = number;
 }
 @Override
 public void run() {
  System.out.println(number.getNumber(8));
 }
}

在main函數(shù)中創(chuàng)建兩個線程類,包含了同一個Number類實例的引用:

public static void main(String[] args) {

 Number number = new Number();
 //兩個線程操作同一個對象,共享對象number的成員變量number
 MyThread4 myThread = new MyThread4(number);
 MyThread4 myThread2 = new MyThread4(number);
 myThread.start();
 myThread2.start();
}

這樣,當?shù)谝粋€線程讀取Number中的number變量時先保存下來再休眠0.1秒,然后第二個線程再讀取number變量并保存,此時兩個線程保存了同樣的數(shù)字,在修改時,也就導致修改了同一個數(shù)字兩次。

2、同步機制的實現(xiàn):

在多線程并發(fā)編程中Synchronized一直是元老級角色,很多人都會稱呼它為重量級鎖,但是隨著Java SE1.6對Synchronized進行了各種優(yōu)化之后,有些情況下它并不那么重了”
Java中的每一個對象都可以作為鎖。

對于同步方法,鎖是當前實例對象。
對于靜態(tài)同步方法,鎖是當前對象的Class對象。
對于同步方法塊,鎖是Synchonized括號里配置的對象。
當一個線程試圖訪問同步代碼塊時,它首先必須得到鎖,退出或拋出異常時必須釋放鎖。
2.1、使用synchronized關鍵字創(chuàng)建synchronized方法:
使用synchronized關鍵字,該關鍵字修飾的方法叫做同步方法。

Java中每個對象都有一個鎖或者稱為監(jiān)視器,當訪問某個對象的synchronized方法時,表示將該對象上鎖,而不僅僅是為該方法上鎖。

這樣如果一個對象的synchronized方法被某個線程執(zhí)行時,其他線程無法訪問該對象的任何synchronized方法(但是可以調用其他非synchronized的方法)。直至該synchronized方法執(zhí)行完。

靜態(tài)的synchronized方法調用情況:
當調用一個對象的靜態(tài)synchronized方法時,它鎖定的并不是synchronized方法所在的對象,而是synchronized方法所在對象對應的Class對象。這樣,其他線程就不能調用該類的其他靜態(tài)synchronized方法了,但是可以調用非靜態(tài)的synchronized方法。

結論:執(zhí)行靜態(tài)synchronized方法鎖方法所在對象,執(zhí)行非靜態(tài)synchronized方法鎖方法所在對象對應的Class對象。

下面是多線程調用靜態(tài)的方法的例子,由于鎖定了方法所在對象對應的Class對象,其他線程無法調用該方法所在對象其他的靜態(tài)synchronized方法:

/**
 * 定義一個類,包含了線程類需要調用的方法
 */
class Compute1{
 //這時如果某個線程調用該方法,
 //將鎖定synchronized方法所在對象對應的class對象,
 //而不是鎖定synchronized方法所在對象
 public synchronized static void execute(){
  for(int i = 0; i<100; i++){
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("compute1:execute1 " + i++);
  }
 }
 public synchronized static void execute2(){
  for(int i = 0; i<100; i++){
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("compute1:execute2 " + i++);
  }
 }
}

main方法中兩個線程分別調用同一個對象的兩個static synchronized方法:

public static void main(String[] args) {
 Compute1 com = new Compute1();
 Thread thread1 = new Thread1(com);
 Thread thread2 = new Thread2(com);
 thread1.start();
 thread2.start();
}

一次只能調用一個靜態(tài)方法,直到執(zhí)行完成。

2.2、使用synchronized創(chuàng)建同步代碼塊:
通過使用synchronized同步代碼塊,鎖定一個對象,該對象作為可執(zhí)行的標志從而達到同步的效果:

/**
 * 定義一個類,包含了線程類需要調用的方法
 */
class Compute1{
 //通過同步代碼塊鎖定object1對象進行鎖定了其他同樣的synchronized代碼塊
 private Object object1 = new Object();
 public void execute(){
  synchronized(object1){
   for(int i = 0; i<100; i++){
    try {
     Thread.sleep(100);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println("compute1:execute1 " + i++);
   }
  }

 }
 public synchronized void execute2(){
  synchronized(object1){
   for(int i = 0; i<100; i++){
    try {
     Thread.sleep(100);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println("compute1:execute2 " + i++);
   }
  }
 }
}

如果想要使用synchronized同步代碼塊達到和使用synchronized方法同樣的效果,可以鎖定this引用:

synchronized(this){
 …
}

2.3、synchronized方法和synchronized同步代碼塊的區(qū)別:
synchronized同步代碼塊只是鎖定了該代碼塊,代碼塊外面的代碼還是可以被訪問的。

synchronized方法是粗粒度的并發(fā)控制,某一個時刻只能有一個線程執(zhí)行該synchronized方法。

synchronized同步代碼塊是細粒度的并發(fā)控制,只會將塊中的代碼同步,代碼塊之外的代碼可以被其他線程同時訪問。

相關文章

  • SpringBoot整合MyBatis的代碼詳解

    SpringBoot整合MyBatis的代碼詳解

    這篇文章主要介紹了SpringBoot整合MyBatis筆記記錄,大家需要注意在整合mybatis之前我們需要相對應的導入相關依賴,首先需要在java的目錄和resources下創(chuàng)建mapper文件夾,對SpringBoot整合MyBatis的詳細過程感興趣的朋友一起看看吧
    2022-05-05
  • Kafka Java Producer代碼實例詳解

    Kafka Java Producer代碼實例詳解

    這篇文章主要介紹了Kafka Java Producer代碼實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Spark學習筆記之Spark中的RDD的具體使用

    Spark學習筆記之Spark中的RDD的具體使用

    這篇文章主要介紹了Spark學習筆記之Spark中的RDD的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-06-06
  • spring XML配置文件標簽詳解

    spring XML配置文件標簽詳解

    這篇文章主要介紹了spring XML配置文件標簽詳解,本文給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2024-12-12
  • Java容器ArrayList知識點總結

    Java容器ArrayList知識點總結

    本篇文章給大家分享了Java容器ArrayList的相關知識點,對此有需要的朋友可以跟著學習參考下。
    2018-05-05
  • Spring Boot 項目啟動失敗的解決方案

    Spring Boot 項目啟動失敗的解決方案

    這篇文章主要介紹了Spring Boot 項目啟動失敗的解決方案,幫助大家更好的理解和學習使用Spring Boot,感興趣的朋友可以了解下
    2021-03-03
  • Spring中BeanFactory解析bean詳解

    Spring中BeanFactory解析bean詳解

    本篇文章主要介紹了Spring中BeanFactory解析bean詳解 ,詳細的介紹了使用BeanFactory對bean進行解析的實例,有興趣的可以了解一下。
    2017-04-04
  • MyBatis 結果映射的幾種實現(xiàn)方式

    MyBatis 結果映射的幾種實現(xiàn)方式

    本文主要介紹了MyBatis中的結果映射機制,包括映射方式及其在處理關聯(lián)關系中的高級應用,具有一定的參考價值,感興趣的可以了解一下
    2025-09-09
  • Java中實現(xiàn)訂單超時自動取消功能(最新推薦)

    Java中實現(xiàn)訂單超時自動取消功能(最新推薦)

    本文介紹了Java中實現(xiàn)訂單超時自動取消功能的幾種方法,包括定時任務、JDK延遲隊列、Redis過期監(jiān)聽、Redisson分布式延遲隊列、RocketMQ延遲消息和RabbitMQ死信隊列,每種方法都有其優(yōu)缺點,可以根據(jù)具體需求選擇合適的方法,感興趣的朋友一起看看吧
    2025-02-02
  • springboot實現(xiàn)小程序支付的項目實踐

    springboot實現(xiàn)小程序支付的項目實踐

    本文主要介紹了springboot實現(xiàn)小程序支付的項目實踐,?可以通過調用微信支付?API?實現(xiàn)支付功能,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09

最新評論

涞源县| 宁德市| 石泉县| 马尔康县| 沙雅县| 资兴市| 福安市| 瑞金市| 尉犁县| 应用必备| 郯城县| 彭阳县| 铁岭县| 太保市| 太仓市| 安塞县| 崇文区| 钦州市| 修文县| 江山市| 吉木乃县| 繁峙县| 定州市| 惠水县| 宁明县| 邻水| 景德镇市| 轮台县| 旬阳县| 文化| 固安县| 久治县| 华坪县| 高阳县| 婺源县| 阿拉善左旗| 康定县| 安新县| 库伦旗| 镇平县| 彩票|