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

淺析Java 并發(fā)編程中的synchronized

 更新時(shí)間:2020年12月03日 09:00:04   作者:拾階求上  
這篇文章主要介紹了Java 并發(fā)編程中的synchronized的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java并發(fā)編程,感興趣的朋友可以了解下

synchronized關(guān)鍵字,我們一般稱之為“同步鎖”,用它來(lái)修飾需要同步的方法和需要同步代碼塊,默認(rèn)是當(dāng)前對(duì)象作為鎖的對(duì)象。在用synchronized修飾類時(shí)(或者修飾靜態(tài)方法),默認(rèn)是當(dāng)前類的Class對(duì)象作為鎖的對(duì)象,故存在著方法鎖、對(duì)象鎖、類鎖這樣的概念。

一、沒(méi)有設(shè)置線程同步的情況

先給出以下代碼感受下代碼執(zhí)行的時(shí)候?yàn)槭裁葱枰??代碼可能比較枯燥,配上業(yè)務(wù)理解起來(lái)就會(huì)舒服很多,學(xué)生軍訓(xùn),有三列,每列5人,需要報(bào)數(shù),每個(gè)線程負(fù)責(zé)每一列報(bào)數(shù)。

class SynchronizedExample {
	protected static int num = 0;
	protected void numberOff() {
		for(int i=0; i<5; i++) {
			num++;
System.out.println(Thread.currentThread().getName()+":"+SynchronizedExample.num);
		}
	}
}

public class SynchronizedTest {
	public static void main(String[] args) throws InterruptedException {
		SynchronizedExample se = new SynchronizedExample();
		for(int i=1; i<=3; i++) {
			new Thread( ()-> {se.numberOff();}, "線程"+i).start();
		}
	}
}

執(zhí)行結(jié)果如下:

線程1:1
線程2:2
線程1:3
線程3:4
.......

之所以出現(xiàn)這種情況,是因?yàn)槿齻€(gè)線程是異步的,沒(méi)有同步。
對(duì)應(yīng)的業(yè)務(wù)場(chǎng)景就是,在第一列沒(méi)有完成報(bào)數(shù)的時(shí)候,其他隊(duì)列搶報(bào)了,這在現(xiàn)實(shí)中是不允許的,所以需要類似于synchronized等具有同步功能的關(guān)鍵字粉末登場(chǎng)。

二、方法同步鎖

當(dāng)報(bào)數(shù)方法加上synchronized關(guān)鍵字之后,就會(huì)一列一列的報(bào)數(shù)。

protected synchronized void numberOff() {
	for(int i=0; i<5; i++) {
		num++;
System.out.println(Thread.currentThread().getName()+":"+SynchronizedExample.num);
	}
}

執(zhí)行結(jié)果如下:

線程1:1
線程1:2
線程1:3
線程1:4
......

寫到這里還是要從技術(shù)層面講下原理,當(dāng)一個(gè)線程執(zhí)行帶有synchronized關(guān)鍵字的方法時(shí),該線程會(huì)在該方法處設(shè)置一個(gè)鎖(其他線程打不開這個(gè)鎖,只能在外邊等該線程釋放掉該鎖,一般都是執(zhí)行完所有代碼后主動(dòng)釋放鎖),表示此方法是當(dāng)前線程獨(dú)占的,對(duì)應(yīng)到上述業(yè)務(wù)中就是一次只能有一個(gè)隊(duì)列報(bào)數(shù)。

三、對(duì)象鎖

改進(jìn)后的代碼用到了一個(gè)對(duì)象鎖,該對(duì)象鎖默認(rèn)是當(dāng)前對(duì)象,上述代碼等同于以下代碼:

protected void numberOff() {
	synchronized (this) {
		for (int i = 0; i < 5; i++) {
			num++;
			System.out.println(Thread.currentThread().getName() + ":" + SynchronizedExample.num);
		}
	}
}

當(dāng)多個(gè)線程用一個(gè)對(duì)象鎖,各個(gè)線程可以達(dá)到同步的作用,如果每個(gè)線程都用自己的對(duì)象鎖,那么synchronized就失去了同步的作用。如以下代碼:

class SynchronizedExample {
	protected static int num = 0;
	protected void numberOff() {
		synchronized (this) {
			for (int i = 0; i < 5; i++) {
				num++;
			System.out.println(Thread.currentThread().getName() + ":" + SynchronizedExample.num);
			}
		}
	}
}
public class SynchronizedTest {
	public static void main(String[] args) throws InterruptedException {
		SynchronizedExample se = new SynchronizedExample();
		for(int i=1; i<=3; i++) {
			new Thread( ()-> {new SynchronizedExample().numberOff();}, "隊(duì)列"+i).start();
		}
	}
}

執(zhí)行結(jié)果如下:

線程1:1
線程2:2
線程1:3
線程3:4
.......

有讀者會(huì)說(shuō)不同線程執(zhí)行的是不同對(duì)象中的方法,肯定達(dá)不到同步的效果,也對(duì),也很有道理,接著看如下代碼:

class SynchronizedExample {
	protected static int num = 0;
	protected void numberOff(Object lock) {
		synchronized (lock) {
			for (int i = 0; i < 5; i++) {
				num++;
			System.out.println(Thread.currentThread().getName() + ":" + SynchronizedExample.num);
			}
		}
	}
}

public class SynchronizedTest {
	public static void main(String[] args) throws InterruptedException {
		SynchronizedExample se = new SynchronizedExample();
		for(int i=1; i<=3; i++) {
			new Thread( ()-> {se.numberOff(new Object());}, "隊(duì)列"+i).start();
		}
	}
}

執(zhí)行結(jié)果如下:

線程1:1
線程2:2
線程1:3
線程3:4
.......

四、類鎖

對(duì)于上述問(wèn)題,讀者應(yīng)該得出一個(gè)結(jié)論,要想達(dá)到同步的效果,必須用同一個(gè)鎖,此時(shí)類鎖可以粉末登場(chǎng)??慈缦麓a:

protected void numberOff(Object lock) {
	synchronized (SynchronizedExample.class) {
		for (int i = 0; i < 5; i++) {
			num++;
			System.out.println(Thread.currentThread().getName() + ":" + SynchronizedExample.num);
		}
	}
}

上述代碼可以達(dá)到同步的效果。

五、靜態(tài)鎖

靜態(tài)鎖是針對(duì)靜態(tài)方法而言,當(dāng)一個(gè)靜態(tài)方法中有synchronized關(guān)鍵字時(shí),默認(rèn)的是使用當(dāng)前類字節(jié)碼對(duì)象作為鎖。代碼示例如下:

class SynchronizedExample {
	protected static int num = 0;
	protected synchronized static void numberOff() {
		for (int i = 0; i < 5; i++) {
			num++;
			System.out.println(Thread.currentThread().getName() + ":" + SynchronizedExample.num);
		}
	}
}

public class SynchronizedTest {
	public static void main(String[] args) throws InterruptedException {
		for (int i = 1; i <= 3; i++) {
			new Thread(() -> { new SynchronizedExample().numberOff(); }, "隊(duì)列" + i).start();
		}
	}
}

六、線程池實(shí)現(xiàn)

最后用線程池將上述代碼寫一下

package ioo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class SynchronizedExample {
	protected static int num = 0;
	protected synchronized static void numberOff() {
		for (int i = 0; i < 5; i++) {
			num++;
			System.out.println(Thread.currentThread().getName() + ":" + SynchronizedExample.num);
		}
	}
}

public class SynchronizedTest {
	public static void main(String[] args) throws InterruptedException {
		ExecutorService executorService = Executors.newCachedThreadPool();
		for(int i=1; i<=3; i++) {
			executorService.execute(() -> new SynchronizedExample().numberOff());
		}
	}
}

以上就是淺析Java 并發(fā)編程中的synchronized的詳細(xì)內(nèi)容,更多關(guān)于Java 并發(fā)編程 synchronized的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java實(shí)現(xiàn)簡(jiǎn)單的五子棋游戲

    java實(shí)現(xiàn)簡(jiǎn)單的五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Spring輕松解決循環(huán)依賴

    Spring輕松解決循環(huán)依賴

    Spring的解決循環(huán)依賴是有前置條件的,要解決循環(huán)依賴我們首先要了解Spring Bean對(duì)象的創(chuàng)建過(guò)程和依賴注入的方式。依賴注入方式,我之前的博客有所分享,大家可以在看本篇文章之前進(jìn)行一下小小的回顧
    2023-04-04
  • spring動(dòng)態(tài)注冊(cè)bean?AOP失效原理解析

    spring動(dòng)態(tài)注冊(cè)bean?AOP失效原理解析

    這篇文章主要為大家介紹了spring動(dòng)態(tài)注冊(cè)bean使AOP失效原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • logback 配置詳解(推薦)

    logback 配置詳解(推薦)

    這篇文章主要介紹了logback 配置詳解(推薦),詳細(xì)的介紹了logback的組成使用和配置,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • java HashMap通過(guò)value反查key的代碼示例

    java HashMap通過(guò)value反查key的代碼示例

    本文講解了java HashMap通過(guò)value反查key的方法,直接提供代碼供大家參考使用
    2013-11-11
  • SpringBoot集成MyBatis的三種方式

    SpringBoot集成MyBatis的三種方式

    Spring Boot與MyBatis的集成為Java開發(fā)者提供了一種簡(jiǎn)便而強(qiáng)大的方式來(lái)訪問(wèn)和操作數(shù)據(jù)庫(kù),在本文中,我們將深入解析Spring Boot集成MyBatis的多種方式,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2023-12-12
  • 如何在spring boot中進(jìn)行參數(shù)校驗(yàn)示例詳解

    如何在spring boot中進(jìn)行參數(shù)校驗(yàn)示例詳解

    這篇文章主要介紹了如何在spring-boot中進(jìn)行參數(shù)校驗(yàn)及l(fā)ombok的使用詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Java中==符號(hào)與equals()的使用詳解(測(cè)試兩個(gè)變量是否相等)

    Java中==符號(hào)與equals()的使用詳解(測(cè)試兩個(gè)變量是否相等)

    下面小編就為大家?guī)?lái)一篇Java中==符號(hào)與equals()的使用詳解(測(cè)試兩個(gè)變量是否相等)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • Java集合之Disruptor操作示例

    Java集合之Disruptor操作示例

    這篇文章主要為大家介紹了Java集合之Disruptor操作示例介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 選擇java的理由:java之父訪談實(shí)錄

    選擇java的理由:java之父訪談實(shí)錄

    選擇java的理由:java之父訪談實(shí)錄...
    2006-12-12

最新評(píng)論