程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java多線程編程之Synchronized塊同步辦法

java多線程編程之Synchronized塊同步辦法

編輯:關於JAVA

java多線程編程之Synchronized塊同步辦法。本站提示廣大學習愛好者:(java多線程編程之Synchronized塊同步辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是java多線程編程之Synchronized塊同步辦法正文


文章分享了4個例子對synchronized的具體說明

1、能否加synchronized症結字的分歧

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();

    Thread t1 = new Thread1(example);
    Thread t2 = new Thread1(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }

  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

加了synchronized症結字的輸入成果以下

會先輸入一組0-4,接著再輸入下一組,兩個線程次序履行

excute:0
excute:1
excute:2
excute:3
excute:4
excute:0
excute:1
excute:2
excute:3
excute:4

沒加synchronized症結字的輸入成果以下

兩個線程同時履行excute辦法,同時並發的

excute:0
excute:0
excute:1
excute:1
excute:2
excute:2
excute:3
excute:3
excute:4
excute:4

2、多個辦法的多線程情形

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();

    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }
  }
  public synchronized void excute1() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute1:" + i);
    }
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

履行成果以下

異樣是次序履行,履行完一個線程再履行另外一個線程

excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4

假如去失落synchronized症結字,則兩個辦法並發履行,並沒有互相影響。

然則如例子法式中所寫,即使是兩個辦法:

履行成果永久是履行完一個線程的輸入再履行另外一個線程的。  

解釋:

  假如一個對象有多個synchronized辦法,某一時辰某個線程曾經進入到了某個synchronized辦法,那末在該辦法沒有履行終了前,其他線程是沒法拜訪該對象的任何synchronized辦法的。

結論:

  當synchronized症結字潤飾一個辦法的時刻,該辦法叫做同步辦法。

  Java中的每一個對象都有一個鎖(lock),或許叫做監督器(monitor),當一個線程拜訪某個對象的synchronized辦法時,將該對象上鎖,其他任何線程都沒法再去拜訪該對象的synchronized辦法了(這裡是指一切的同步辦法,而不只僅是統一個辦法),直到之前的誰人線程履行辦法終了後(或許是拋出了異常),才將該對象的鎖釋放失落,其他線程才有能夠再去拜訪該對象的synchronized辦法。

  留意這時候候是給對象上鎖,假如是分歧的對象,則各個對象之間沒無限制關系。

  測驗考試在代碼中結構第二個線程對象時傳入一個新的Example對象,則兩個線程的履行之間沒有甚麼制約關系。

3、靜態的同步辦法

當一個synchronized症結字潤飾的辦法同時又被static潤飾,之前說過,非靜態的同步辦法會將對象上鎖,然則靜態辦法不屬於對象,而是屬於類,它會將這個辦法地點的類的Class對象上鎖。

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();
    Example example2 = new Example();
    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example2);
    t1.start();
    t2.start();
  }
}

class Example {
  public synchronized static void excute() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute:" + i);
    }
  }
  public synchronized static void excute1() {
    for (int i = 0; i < 5; ++i) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("excute1:" + i);
    }
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

履行成果以下

excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4

假如沒有static潤飾符,兩個線程分離傳入分歧的對象,則會同時並發履行

所以假如是靜態辦法的情形(execute()和execute2()都加上static症結字),即使是向兩個線程傳入分歧的Example對象,這兩個線程依然是相互制約的,必需先履行完一個,再履行下一個。

結論:

  假如某個synchronized辦法是static的,那末當線程拜訪該辦法時,它鎖的其實不是synchronized辦法地點的對象,而是synchronized辦法地點的類所對應的Class對象。Java中,不管一個類有若干個對象,這些對象會對應獨一一個Class對象,是以當線程分離拜訪統一個類的兩個對象的兩個static,synchronized辦法時,它們的履行次序也是次序的,也就是說一個線程先去履行辦法,履行終了後另外一個線程才開端。

4.synchronized塊

synchronized(object)

{     

}

表現線程在履行的時刻會將object對象上鎖。(留意這個對象可所以隨意率性類的對象,也能夠應用this症結字)。

如許便可以自行劃定上鎖對象。

public class ThreadTest {

  public static void main(String[] args) {
    Example example = new Example();
    Thread t1 = new Thread1(example);
    Thread t2 = new Thread2(example);
    t1.start();
    t2.start();
  }
}

class Example {
  public void excute() {
    synchronized (this) {
      for (int i = 0; i < 5; ++i) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("excute:" + i);
      }
    }
    
  }
  public void excute1() {
    synchronized (this) {
      for (int i = 0; i < 5; ++i) {
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("excute1:" + i);
      }
    }
    
  }

}

class Thread1 extends Thread {
  private Example example;

  public Thread1(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute();
  }
}

class Thread2 extends Thread {
  private Example example;

  public Thread2(Example example) {
    this.example = example;
  }

  @Override
  public void run() {
    example.excute1();
  }
}

履行成果以下

excute:0
excute:1
excute:2
excute:3
excute:4
excute1:0
excute1:1
excute1:2
excute1:3
excute1:4

例子法式4所到達的後果和例子法式2的後果一樣,都是使得兩個線程的履行次序停止,而不是並發停止,當一個線程履行時,將object對象鎖住,另外一個線程就不克不及履行對應的塊。

synchronized辦法現實上同等於用一個synchronized塊包住辦法中的一切語句,然後在synchronized塊的括號中傳入this症結字。固然,假如是靜態辦法,須要鎖定的則是class對象。  

能夠一個辦法中只要幾行代碼會觸及到線程同步成績,所以synchronized塊比synchronized辦法加倍細粒度地掌握了多個線程的拜訪,只要synchronized塊中的內容不克不及同時被多個線程所拜訪,辦法中的其他語句依然可以同時被多個線程所拜訪(包含synchronized塊之前的和以後的)。

結論:

  synchronized辦法是一種粗粒度的並發掌握,某一時辰,只能有一個線程履行該synchronized辦法;

  synchronized塊則是一種細粒度的並發掌握,只會將塊中的代碼同步,位於辦法內、synchronized塊以外的其他代碼是可以被多個線程同時拜訪到的。

以上就是關於java多線程編程Synchronized塊同步辦法,願望對年夜家的進修有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved