真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java多線程同步實(shí)現(xiàn)的方式是什么

這篇文章主要講解了“Java多線程同步實(shí)現(xiàn)的方式是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java多線程同步實(shí)現(xiàn)的方式是什么”吧!

創(chuàng)新互聯(lián)建站,專注為中小企業(yè)提供官網(wǎng)建設(shè)、營銷型網(wǎng)站制作、響應(yīng)式網(wǎng)站開發(fā)、展示型成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)等服務(wù),幫助中小企業(yè)通過網(wǎng)站體現(xiàn)價(jià)值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營銷推廣問題。

給我一把鎖,我能創(chuàng)造一個(gè)規(guī)矩

很多人都知道,在Java多線程編程中,有一個(gè)重要的關(guān)鍵字,synchronized。但是很多人看到這個(gè)東西會(huì)感到困惑:“都說同步機(jī)制是通過對象鎖來實(shí)現(xiàn)的,但是這么一個(gè)關(guān)鍵字,我也看不出來Java程序鎖住了哪個(gè)對象阿?“

沒錯(cuò),我一開始也是對這個(gè)問題感到困惑和不解。不過還好,我們有下面的這個(gè)例程:

public class ThreadTest extends Thread {  private int threadNo;  public ThreadTest(int threadNo) {  this.threadNo = threadNo;  }  public static void main(String[] args) throws Exception {  for (int i = 1; i < 10; i++) {  new ThreadTest(i).start();  Thread.sleep(1);  }  }  @Override public synchronized void run() {  for (int i = 1; i < 10000; i++) {  System.out.println("No." + threadNo + ":" + i);  }  }  }

這個(gè)程序其實(shí)就是讓10個(gè)線程在控制臺(tái)上數(shù)數(shù),從1數(shù)到9999。理想情況下,我們希望看到一個(gè)線程數(shù)完,然后才是另一個(gè)線程開始數(shù)數(shù)。但是這個(gè)程序的執(zhí)行過程告訴我們,這些線程還是亂糟糟的在那里搶著報(bào)數(shù),絲毫沒有任何規(guī)矩可言。

但是細(xì)心的讀者注意到:run方法還是加了一個(gè)synchronized關(guān)鍵字的,按道理說,這些線程應(yīng)該可以一個(gè)接一個(gè)的執(zhí)行這個(gè)run方法才對阿。

但是通過上一篇中,我們提到的,對于一個(gè)成員方法加synchronized關(guān)鍵字,這實(shí)際上是以這個(gè)成員方法所在的對象本身作為對象鎖。在本例中,就是以ThreadTest類的一個(gè)具體對象,也就是該線程自身作為對象鎖的。一共十個(gè)線程,每個(gè)線程持有自己 線程對象的那個(gè)對象鎖。這必然不能產(chǎn)生同步的效果。換句話說,如果要對這些線程進(jìn)行同步,那么這些線程所持有的對象鎖應(yīng)當(dāng)是共享且***的!

我們來看下面的例程:

public class ThreadTest2 extends Thread {  private int threadNo;  private String lock;  public ThreadTest2(int threadNo, String lock) {  this.threadNo = threadNo;  this.lock = lock;  }  public static void main(String[] args) throws Exception {  String lock = new String("lock");  for (int i = 1; i < 10; i++) {  new ThreadTest2(i, lock).start();  Thread.sleep(1);  }  }  public void run() {  synchronized (lock) {  for (int i = 1; i < 10000; i++) {  System.out.println("No." + threadNo + ":" + i);  }  }  }  }

我們注意到,該程序通過在main方法啟動(dòng)10個(gè)線程之前,創(chuàng)建了一個(gè)String類型的對象。并通過ThreadTest2的構(gòu)造函數(shù),將這個(gè)對象賦值給每一個(gè)ThreadTest2線程對象中的私有變量lock。根據(jù)Java方法的傳值特點(diǎn),我們知道,這些線程的lock變量實(shí)際上指向的是堆內(nèi)存中的同一個(gè)區(qū)域,即存放main函數(shù)中的lock變量的區(qū)域。

程序?qū)⒃瓉韗un方法前的synchronized關(guān)鍵字去掉,換用了run方法中的一個(gè)synchronized塊來實(shí)現(xiàn)。這個(gè)同步塊的對象鎖,就是 main方法中創(chuàng)建的那個(gè)String對象。換句話說,他們指向的是同一個(gè)String類型的對象,對象鎖是共享且***的!

于是,我們看到了預(yù)期的效果:10個(gè)線程不再是爭先恐后的報(bào)數(shù)了,而是一個(gè)接一個(gè)的報(bào)數(shù)。

再來看下面的例程:

public class ThreadTest3 extends Thread {  private int threadNo;  private String lock;  public ThreadTest3(int threadNo) {  this.threadNo = threadNo;  }  public static void main(String[] args) throws Exception {  //String lock = new String("lock");  for (int i = 1; i < 20; i++) {  new ThreadTest3(i).start();  Thread.sleep(1);  }  }  public static synchronized void abc(int threadNo) {  for (int i = 1; i < 10000; i++) {  System.out.println("No." + threadNo + ":" + i);  }  }  public void run() {  abc(threadNo);  }  }

細(xì)心的讀者發(fā)現(xiàn)了:這段代碼沒有使用main方法中創(chuàng)建的String對象作為這10個(gè)線程的線程鎖。而是通過在run方法中調(diào)用本線程中一個(gè)靜態(tài)的同步方法abc而實(shí)現(xiàn)了線程的同步。我想看到這里,你們應(yīng)該很困惑:這里synchronized靜態(tài)方法是用什么來做對象鎖的呢?

我們知道,對于同步靜態(tài)方法,對象鎖就是該靜態(tài)放發(fā)所在的類的Class實(shí)例,由于在JVM中,所有被加載的類都有***的類對象,具體到本例,就是***的 ThreadTest3.class對象。不管我們創(chuàng)建了該類的多少實(shí)例,但是它的類實(shí)例仍然是一個(gè)!

這樣我們就知道了:

1、對于同步的方法或者代碼塊來說,必須獲得對象鎖才能夠進(jìn)入同步方法或者代碼塊進(jìn)行操作;

2、如果采用method級(jí)別的同步,則對象鎖即為method所在的對象,如果是靜態(tài)方法,對象鎖即指method所在的
Class對象(***);

3、對于代碼塊,對象鎖即指synchronized(abc)中的abc;

4、因?yàn)?**種情況,對象鎖即為每一個(gè)線程對象,因此有多個(gè),所以同步失效,第二種共用同一個(gè)對象鎖lock,因此同步生效,第三個(gè)因?yàn)槭莝tatic因此對象鎖為ThreadTest3的class 對象,因此同步生效。

如上述正確,則同步有兩種方式,同步塊和同步方法(為什么沒有wait和notify?這個(gè)我會(huì)在補(bǔ)充章節(jié)中做出闡述)

如果是同步代碼塊,則對象鎖需要編程人員自己指定,一般有些代碼為synchronized(this)只有在單態(tài)模式才生效;
(本類的實(shí)例有且只有一個(gè))

如果是同步方法,則分靜態(tài)和非靜態(tài)兩種。

靜態(tài)方法則一定會(huì)同步,非靜態(tài)方法需在單例模式才生效,推薦用靜態(tài)方法(不用擔(dān)心是否單例)。

所以說,在Java多線程編程中,最常見的synchronized關(guān)鍵字實(shí)際上是依靠對象鎖的機(jī)制來實(shí)現(xiàn)線程同步的。
我們似乎可以聽到synchronized在向我們說:“給我一把鎖,我能創(chuàng)造一個(gè)規(guī)矩”。

感謝各位的閱讀,以上就是“Java多線程同步實(shí)現(xiàn)的方式是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Java多線程同步實(shí)現(xiàn)的方式是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


當(dāng)前名稱:Java多線程同步實(shí)現(xiàn)的方式是什么
分享URL:http://weahome.cn/article/jjoeij.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部