国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【創(chuàng)作贏紅包】Java多線程:synchronized鎖方法塊

這篇具有很好參考價值的文章主要介紹了【創(chuàng)作贏紅包】Java多線程:synchronized鎖方法塊。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

synchronized同步代碼塊
用關(guān)鍵字synchronized聲明方法在某些情況下是有弊端的,比如A線程調(diào)用同步方法執(zhí)行一個較長時間的任務(wù),那么B線程必須等待比較長的時間。這種情況下可以嘗試使用synchronized同步語句塊來解決問題??匆幌吕樱?/span>
???
?public class ThreadDomain18 {
????????public void doLongTimeTask() throws Exception {
????????????for (int i = 0; i < 100; i++) {
????????????????System.out.println(
????????????????????????"nosynchronized threadName = " + Thread.currentThread().getName() + ", i = " + (i + 1));
????????????}
????????????System.out.println();
????????????synchronized (this) {
????????????????for (int i = 0; i < 100; i++) {
????????????????????System.out.println(
????????????????????????????"synchronized threadName = " + Thread.currentThread().getName() + ", i = " + (i + 1));
????????????????}
????????????}
????????}
????}
public class MyThread18 extends Thread {
????????private ThreadDomain18 td;

????????public MyThread18(ThreadDomain18 td) {
????????????this.td = td;
????????}

????????public void run() {
????????????try {
????????????????td.doLongTimeTask();
????????????} catch (Exception e) {
????????????????e.printStackTrace();
????????????}
????????}
????}
public static void main(String[] args){
?? ?ThreadDomain18 td = new ThreadDomain18();
?? ?MyThread18 mt0 = new MyThread18(td);
?? ?MyThread18 mt1 = new MyThread18(td);
?? ?mt0.start();
?? ?mt1.start();
}
運行結(jié)果,分兩部分來看:
synchronized threadName = Thread-1, i = 1
synchronized threadName = Thread-1, i = 2
nosynchronized threadName = Thread-0, i = 95
synchronized threadName = Thread-1, i = 3
nosynchronized threadName = Thread-0, i = 96
synchronized threadName = Thread-1, i = 4
nosynchronized threadName = Thread-0, i = 97
synchronized threadName = Thread-1, i = 5
nosynchronized threadName = Thread-0, i = 98
synchronized threadName = Thread-1, i = 6
nosynchronized threadName = Thread-0, i = 99
synchronized threadName = Thread-1, i = 7
nosynchronized threadName = Thread-0, i = 100
...
synchronized threadName = Thread-1, i = 98
synchronized threadName = Thread-1, i = 99
synchronized threadName = Thread-1, i = 100
synchronized threadName = Thread-0, i = 1
synchronized threadName = Thread-0, i = 2
synchronized threadName = Thread-0, i = 3
...
這個實驗可以得出以下兩個結(jié)論:
1、 當(dāng)A線程訪問對象的synchronized代碼塊的時候,B線程依然可以訪問對象方法中其余非synchronized塊的部分,第一部分的執(zhí)行結(jié)果證明了這一點
2、 當(dāng)A線程進(jìn)入對象的synchronized代碼塊的時候,B線程如果要訪問這段synchronized塊,那么訪問將會被阻塞,第二部分的執(zhí)行結(jié)果證明了這一點
所以,從執(zhí)行效率的角度考慮,有時候我們未必要把整個方法都加上synchronized,而是可以采取synchronized塊的方式,對會引起線程安全問題的那一部分代碼進(jìn)行synchronized就可以了。
兩個synchronized塊之間具有互斥性
如果線程1訪問了一個對象A方法的synchronized塊,那么線程B對同一對象B方法的synchronized塊的訪問將被阻塞,寫個例子來證明一下:
?public class ThreadDomain19 {
????????public void serviceMethodA() {
????????????synchronized (this) {
????????????????try {
????????????????????System.out.println("A begin time = " + System.currentTimeMillis());
????????????????????Thread.sleep(2000);
????????????????????System.out.println("A end time = " + System.currentTimeMillis());
????????????????} catch (InterruptedException e) {
????????????????????e.printStackTrace();
????????????????}
????????????}
????????}

????????public void serviceMethodB() {
????????????synchronized (this) {
????????????????System.out.println("B begin time = " + System.currentTimeMillis());
????????????????System.out.println("B end time = " + System.currentTimeMillis());
????????????}
????????}
????}
寫兩個線程分別調(diào)用這兩個方法:
public class MyThread19_0 extends Thread{
?? ?private ThreadDomain19 td;
?? ?public MyThread19_0(ThreadDomain19 td){
?? ??? ?this.td = td;
?? ?}
?? ?public void run(){
?? ??? ?td.serviceMethodA();
?? ?}
}
public class MyThread19_1 extends Thread{
?? ?private ThreadDomain19 td;
?? ?public MyThread19_1(ThreadDomain19 td){
?? ??? ?this.td = td;
?? ?}
?? ?public void run(){
?? ??? ?td.serviceMethodB();
?? ?}
}
寫個main函數(shù):
public static void main(String[] args){
?? ?ThreadDomain19 td = new ThreadDomain19();
?? ?MyThread19_0 mt0 = new MyThread19_0(td);
?? ?MyThread19_1 mt1 = new MyThread19_1(td);
?? ?mt0.start();
?? ?mt1.start();
}
看一下運行結(jié)果:
A begin time = 1443843271982
A end time = 1443843273983
B begin time = 1443843273983
B end time = 1443843273983
看到對于serviceMethodB()方法synchronized塊的訪問必須等到對于serviceMethodA()方法synchronized塊的訪問結(jié)束之后。那其實這個例子,我們也可以得出一個結(jié)論: synchronized塊獲得的是一個對象鎖,換句話說,synchronized塊鎖定的是整個對象 。
synchronized塊和synchronized方法
既然上面得到了一個結(jié)論 synchronized塊獲得的是對象鎖 ,那么如果線程1訪問了一個對象方法A的synchronized塊,線程2對于同一對象同步方法B的訪問應(yīng)該是會被阻塞的,因為線程2訪問同一對象的同步方法B的時候?qū)L試去獲取這個對象的對象鎖,但這個鎖卻在線程1這里。寫一個例子證明一下這個結(jié)論:
???
?public class ThreadDomain20 {
????????public synchronized void otherMethod() {
????????????System.out.println("----------run--otherMethod");
????????}

????????public void doLongTask() {
????????????synchronized (this) {
????????????????for (int i = 0; i < 1000; i++) {
????????????????????System.out.println(
????????????????????????????"synchronized threadName = " + Thread.currentThread().getName() + ", i = " + (i + 1));
????????????????????try {
????????????????????????Thread.sleep(5);
????????????????????} catch (InterruptedException e) {
????????????????????????e.printStackTrace();
????????????????????}
????????????????}
????????????}
????????}
????}
寫兩個線程分別調(diào)用這兩個方法:
public class MyThread20_0 extends Thread{
?? ?private ThreadDomain20 td;
?? ?public MyThread20_0(ThreadDomain20 td){
?? ??? ?this.td = td;
?? ?}
?? ?public void run(){
?? ??? ?td.doLongTask();
?? ?}
}
public class MyThread20_1 extends Thread{
?? ?private ThreadDomain20 td;
?? ?public MyThread20_1(ThreadDomain20 td){
?? ??? ?this.td = td;
?? ?}
?? ?public void run(){
?? ??? ?td.otherMethod();
?? ?}
}
寫個main函數(shù)調(diào)用一下,這里"mt0.start()"后sleep(100)以下是為了確保mt0線程先啟動:
public static void main(String[] args) throws Exception{
?? ?ThreadDomain20 td = new ThreadDomain20();
?? ?MyThread20_0 mt0 = new MyThread20_0(td);
?? ?MyThread20_1 mt1 = new MyThread20_1(td);
?? ?mt0.start();
?? ?Thread.sleep(100);
?? ?mt1.start();
}
看一下運行結(jié)果:
...
synchronized threadName = Thread-0, i = 995
synchronized threadName = Thread-0, i = 996
synchronized threadName = Thread-0, i = 997
synchronized threadName = Thread-0, i = 998
synchronized threadName = Thread-0, i = 999
synchronized threadName = Thread-0, i = 1000
----------run--otherMethod
證明了我們的結(jié)論。為了進(jìn)一步完善這個結(jié)論,把"otherMethod()"方法的synchronized去掉再看一下運行結(jié)果:
...
synchronized threadName = Thread-0, i = 16
synchronized threadName = Thread-0, i = 17
synchronized threadName = Thread-0, i = 18
synchronized threadName = Thread-0, i = 19
synchronized threadName = Thread-0, i = 20
----------run--otherMethod
synchronized threadName = Thread-0, i = 21
synchronized threadName = Thread-0, i = 22
synchronized threadName = Thread-0, i = 23
...
"otherMethod()"方法和"doLongTask()"方法中的synchronized塊異步執(zhí)行了
將任意對象作為對象監(jiān)視器
總結(jié)一下前面的內(nèi)容:
1、synchronized同步方法
(1)對其他synchronized同步方法或synchronized(this)同步代碼塊呈阻塞狀態(tài)
(2)同一時間只有一個線程可以執(zhí)行synchronized同步方法中的代碼
2、synchronized同步代碼塊
(1)對其他synchronized同步方法或synchronized(this)同步代碼塊呈阻塞狀態(tài)
(2)同一時間只有一個線程可以執(zhí)行synchronized(this)同步代碼塊中的代碼
前面都使用synchronized(this)的格式來同步代碼塊,其實 Java還支持對"任意對象"作為對象監(jiān)視器來實現(xiàn)同步的功能 。這個"任意對象"大多數(shù)是 實例變量 方法的參數(shù) ,使用格式為synchronized(非this對象)??匆幌聦⑷我鈱ο笞鳛閷ο蟊O(jiān)視器的使用例子:
public class ThreadDomain21 {
????????private String userNameParam;
????????private String passwordParam;
????????private String anyString = new String();

????????public void setUserNamePassword(String userName, String password) {
????????????try {
????????????????synchronized (anyString) {
????????????????????System.out.println("線程名稱為:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis()?+ " 進(jìn)入同步代碼塊");
????????????????????userNameParam = userName;
????????????????????Thread.sleep(3000);
????????????????????passwordParam = password;
????????????????????System.out.println("線程名稱為:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis()?+ " 離開同步代碼塊");
????????????????}
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}
????????}
????}
寫兩個線程分別調(diào)用一下:
public class MyThread21_0 extends Thread{
?? ?private ThreadDomain21 td;
?? ?public MyThread21_0(ThreadDomain21 td){
?? ??? ?this.td = td;
?? ?}
?? ?public void run(){
?? ??? ?td.setUserNamePassword("A", "AA");
?? ?}
}
public class MyThread21_1 extends Thread{
?? ?private ThreadDomain21 td;
?? ?public MyThread21_1(ThreadDomain21 td){
?? ??? ?this.td = td;
?? ?}
?? ?public void run(){
?? ??? ?td.setUserNamePassword("B", "B");
?? ?}
}
寫一個main函數(shù)調(diào)用一下:
public static void main(String[] args){
?? ?ThreadDomain21 td = new ThreadDomain21();
?? ?MyThread21_0 mt0 = new MyThread21_0(td);
?? ?MyThread21_1 mt1 = new MyThread21_1(td);
?? ?mt0.start();
?? ?mt1.start();
}
看一下運行結(jié)果:
線程名稱為:Thread-0在 1443855101706 進(jìn)入同步代碼塊
線程名稱為:Thread-0在 1443855104708 離開同步代碼塊
線程名稱為:Thread-1在 1443855104708 進(jìn)入同步代碼塊
線程名稱為:Thread-1在 1443855107708 離開同步代碼塊
這個例子證明了: 多個線程持有"對象監(jiān)視器"為同一個對象的前提下,同一時間只能有一個線程可以執(zhí)行synchronized(非this對象x)代碼塊中的代碼 。
鎖非this對象具有一定的優(yōu)點:如果在一個類中有很多synchronized方法,這時雖然能實現(xiàn)同步,但會受到阻塞,從而影響效率。但如果同步代碼塊鎖的是非this對象,則synchronized(非this對象x)代碼塊中的程序與同步方法是異步的,不與其他鎖this同步方法爭搶this鎖,大大提高了運行效率。
注意一下"private String anyString = new String();"這句話,現(xiàn)在它是一個全局對象,因此監(jiān)視的是同一個對象。如果移到try里面,那么對象的監(jiān)視器就不是同一個了,調(diào)用的時候自然是異步調(diào)用,可以自己試一下。
最后提一點,synchronized(非this對象x),這個對象如果是實例變量的話,指的是對象的引用, 只要對象的引用不變,即使改變了對象的屬性,運行結(jié)果依然是同步的 。
細(xì)化synchronized(非this對象x)的三個結(jié)論
synchronized(非this對象x)格式的寫法是將x對象本身作為對象監(jiān)視器,有三個結(jié)論得出:
1、當(dāng)多個線程同時執(zhí)行synchronized(x){}同步代碼塊時呈同步效果
2、當(dāng)其他線程執(zhí)行x對象中的synchronized同步方法時呈同步效果
3、當(dāng)其他線程執(zhí)行x對象方法中的synchronized(this)代碼塊時也呈同步效果
第一點很明顯,第二點和第三點意思類似,無非一個是同步方法,一個是同步代碼塊罷了,舉個例子驗證一下第二點:
?
public class MyObject {
????????public synchronized void speedPrintString() {
????????????System.out.println("speedPrintString__getLock time = " + System.currentTimeMillis() + ", run ThreadName = "?+ Thread.currentThread().getName());
????????????System.out.println("----------");
????????????System.out.println("speedPrintString__releaseLock time = " + System.currentTimeMillis()+ ", run ThreadName = " + Thread.currentThread().getName());
????????}
????}
ThreadDomain24中持有MyObject的引用:
public class ThreadDomain24 {
????????public void testMethod1(MyObject mo) {
????????????try {
????????????????synchronized (mo) {
????????????????????System.out.println("testMethod1__getLock time = " + System.currentTimeMillis()?+ ", run ThreadName = " + Thread.currentThread().getName());
????????????????????Thread.sleep(5000);
????????????????????System.out.println("testMethod1__releaseLock time = " + System.currentTimeMillis()?+ ", run ThreadName = " + Thread.currentThread().getName());
????????????????}
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}?
????????}
????}
寫兩個線程分別調(diào)用" speedPrintString() "方法和" testMethod1(MyObject mo) "方法:
public class MyThread24_0 extends Thread{
?? ?private ThreadDomain24 td;
?? ?private MyObject mo;
?? ?public MyThread24_0(ThreadDomain24 td, MyObject mo){
?? ??? ?this.td = td;
?? ??? ?this.mo = mo;
?? ?}
?? ?public void run() {
?? ??? ?td.testMethod1(mo);
?? ?}
}
public class MyThread24_1 extends Thread{
?? ?private MyObject mo;
?? ?public MyThread24_1(MyObject mo){
?? ??? ?this.mo = mo;
?? ?}
?? ?public void run(){
?? ??? ?mo.speedPrintString();
?? ?}
}
寫一個main函數(shù)啟動這兩個線程:
public static void main(String[] args){
?? ?ThreadDomain24 td = new ThreadDomain24();
?? ?MyObject mo = new MyObject();
?? ?MyThread24_0 mt0 = new MyThread24_0(td, mo);
?? ?MyThread24_1 mt1 = new MyThread24_1(mo);
?? ?mt0.start();
?? ?mt1.start();
}
看一下運行結(jié)果:
testMethod1__getLock time = 1443855939811, run ThreadName = Thread-0
testMethod1__releaseLock time = 1443855944812, run ThreadName = Thread-0
speedPrintString__getLock time = 1443855944812, run ThreadName = Thread-1
----------
speedPrintString__releaseLock time = 1443855944812, run ThreadName = Thread-1
看到"speedPrintString()"方法必須等待"testMethod1(MyObject mo)"方法執(zhí)行完畢才可以執(zhí)行,沒有辦法異步執(zhí)行,證明了第二點的結(jié)論。第三點的驗證方法類似,就不寫代碼證明了。

文章來源地址http://www.zghlxwxcb.cn/news/detail-407800.html

到了這里,關(guān)于【創(chuàng)作贏紅包】Java多線程:synchronized鎖方法塊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Java|多線程與高并發(fā)】線程安全問題以及synchronized使用實例

    【Java|多線程與高并發(fā)】線程安全問題以及synchronized使用實例

    Java多線程環(huán)境下,多個線程同時訪問共享資源時可能出現(xiàn)的數(shù)據(jù)競爭和不一致的情況。 線程安全一直都是一個令人頭疼的問題.為了解決這個問題,Java為我們提供了很多方式. synchronized、ReentrantLock類等。 使用線程安全的數(shù)據(jù)結(jié)構(gòu),例如ConcurrentHashMap、ConcurrentLinkedQueue等

    2024年02月09日
    瀏覽(14)
  • Java關(guān)鍵字之synchronized詳解【Java多線程必備】

    Java關(guān)鍵字之synchronized詳解【Java多線程必備】

    點擊 ? Mr.綿羊的知識星球 ?解鎖更多優(yōu)質(zhì)文章。 目錄 一、介紹 二、特性 1. 線程安全 2. 互斥訪問 3. 可重入性 4. 內(nèi)置鎖 三、實現(xiàn)原理 四、和其他鎖比較 1. 優(yōu)點 2. 缺點 五、注意事項和最佳實踐 六、使用案例 1. 案例一 2. 案例二 ? ? synchronized是Java中最基本的同步機制之一,

    2024年01月24日
    瀏覽(21)
  • Java多線程(4)---死鎖和Synchronized加鎖流程

    Java多線程(4)---死鎖和Synchronized加鎖流程

    目錄 前言 一.synchronized 1.1概念? 1.2Synchronized是什么鎖? 1.3Synchronized加鎖工作過程 1.4其他優(yōu)化操作 二.死鎖 2.1什么是死鎖 2.2死鎖的幾個經(jīng)典場景 2.3死鎖產(chǎn)生的條件 2.4如何解決死鎖 ??個人主頁:tq02的博客_CSDN博客-C語言,Java,Java數(shù)據(jù)結(jié)構(gòu)領(lǐng)域博主 ?? 本文由 tq02 原創(chuàng),首發(fā)于

    2024年02月13日
    瀏覽(16)
  • Java并發(fā)編程(三)線程同步 上[synchronized/volatile]

    Java并發(fā)編程(三)線程同步 上[synchronized/volatile]

    當(dāng)使用多個線程來訪問同一個數(shù)據(jù)時,將會導(dǎo)致數(shù)據(jù)不準(zhǔn)確,相互之間產(chǎn)生沖突,非常容易出現(xiàn)線程安全問題,比如多個線程都在操作同一數(shù)據(jù),都打算修改商品庫存,這樣就會導(dǎo)致數(shù)據(jù)不一致的問題。 所以我們通過線程同步機制來保證線程安全,加入同步鎖以避免在該線程沒有完成

    2024年02月13日
    瀏覽(28)
  • java八股文面試[多線程]——synchronized鎖升級過程

    java八股文面試[多線程]——synchronized鎖升級過程

    速記:偏向-輕量-重量 上面講到鎖有四種狀態(tài),并且會因?qū)嶋H情況進(jìn)行膨脹升級,其膨脹方向是: 無鎖——偏向鎖——輕量級鎖——重量級鎖 ,并且膨脹方向 不可逆 一.鎖升級理論. 在synchronized鎖升級過程中涉及到以下幾種鎖.先說一下這幾種鎖是什么意思. 偏向鎖: 只有一個

    2024年02月10日
    瀏覽(24)
  • 【并發(fā)多線程】java并發(fā)中的Synchronized關(guān)鍵詞

    如果在多線程的環(huán)境中,我們經(jīng)常會遇到資源競爭的情況,比如多個線程要去同時修改同一個共享變量,這時候,就需要對資源的訪問方法進(jìn)行一定的處理,保證同一時間只有一個線程訪問。 java提供了synchronized,方便我們實現(xiàn)上述操作。 我們舉個例子,我們創(chuàng)建一個

    2023年04月13日
    瀏覽(23)
  • java八股文面試[多線程]——synchronized鎖升級詳細(xì)流程

    java八股文面試[多線程]——synchronized鎖升級詳細(xì)流程

    偏向鎖是JDK6中的重要引進(jìn),因為HotSpot作者經(jīng)過研究實踐發(fā)現(xiàn),在大多數(shù)情況下,鎖不僅不存在多線程競爭,而且總是由 同一線程多次獲得 ,為了讓線程獲得鎖的代價更低,引進(jìn)了偏向鎖。 偏向鎖是在 單線程 執(zhí)行代碼塊時使用的機制,如果在多線程并發(fā)的環(huán)境下(即線程

    2024年02月10日
    瀏覽(24)
  • java八股文面試[多線程]——Synchronized的底層實現(xiàn)原理

    java八股文面試[多線程]——Synchronized的底層實現(xiàn)原理

    筆試:畫出Synchronized 線程狀態(tài)流轉(zhuǎn) 實現(xiàn)原理圖 synchronized解決的是多個線程之間訪問資源的同步性,synchronized 翻譯為中文的意思是 同步 ,也稱之為”同步鎖“。 synchronized的作用是保證在 同一時刻 , 被修飾的代碼塊或方法只會有一個線程執(zhí)行,以達(dá)到保證并發(fā)安全的

    2024年02月10日
    瀏覽(25)
  • 【創(chuàng)作贏紅包】項目信息分析表

    【創(chuàng)作贏紅包】項目信息分析表

    項目的背景和問題 項目背景: 很多 父母 都 希望他們的孩子成為優(yōu)秀的人 ,但是在實踐中,他們的教育方式往往會出現(xiàn)一些與期望不符的情況。這可能是因為這些父母很大程度上是按照自己的父母的教育方式來教育孩子的,這導(dǎo)致 一些不太好的方式被沿襲和流傳下來 。,舉

    2023年04月15日
    瀏覽(17)
  • 【創(chuàng)作贏紅包】python學(xué)習(xí)——【第七彈】

    【創(chuàng)作贏紅包】python學(xué)習(xí)——【第七彈】

    上一篇文章 python學(xué)習(xí)——【第六彈】中介紹了 python中的字典操作 ,這篇文章接著學(xué)習(xí)python中的 可變序列 集合 1: 集合是python語言提供的內(nèi)置數(shù)據(jù)結(jié)構(gòu),具有 無序性 (集合中的元素?zé)o法通過索引下標(biāo)訪問,并且每次輸出時元素的排序順序可能都不相同。), 互異性 , 確定

    2023年04月08日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包