久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java中關(guān)鍵字synchronized的使用方法詳解

瀏覽:104日期:2023-02-11 11:48:26

synchronized是Java里的一個(gè)關(guān)鍵字,起到的一個(gè)效果是“監(jiān)視器鎖”~~,它的功能就是保證操作的原子性,同時(shí)禁止指令重排序和保證內(nèi)存的可見(jiàn)性!

public class TestDemo { static class Counter{public int count = 0;public void add(){ count++;} } public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(){ @Override public void run() {for (int i = 0; i < 50000; i++) { counter.add();} }};Thread t2 = new Thread(){ @Override public void run() {for (int i = 0; i < 50000; i++) { counter.add();} }};//啟動(dòng)兩個(gè)線程t1.start();t2.start();//等待兩個(gè)線程結(jié)束t1.join();t2.join();System.out.println(counter.count); }}

Java中關(guān)鍵字synchronized的使用方法詳解

此時(shí)的線程就是不安全的,如何解決呢?

給我們的Counter對(duì)象里的add方法加上synchronized關(guān)鍵字,針對(duì)這個(gè)方法進(jìn)行了加鎖操作。進(jìn)入代碼塊(調(diào)用方法)自動(dòng)加鎖,出了代碼塊(方法結(jié)束),自動(dòng)解鎖。

public class TestDemo { static class Counter{public int count = 0; //修飾方法 synchronized public void add{ count++;} } public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(){ @Override public void run() {for (int i = 0; i < 50000; i++) { counter.add();} }};Thread t2 = new Thread(){ @Override public void run() {for (int i = 0; i < 50000; i++) { counter.add();} }};//啟動(dòng)兩個(gè)線程t1.start();t2.start();//等待兩個(gè)線程結(jié)束t1.join();t2.join();System.out.println(counter.count); }}

Java中關(guān)鍵字synchronized的使用方法詳解

那么這里的代碼是如何保證正確的呢?

使用synchronized 就相當(dāng)于在我們執(zhí)行的指令里又加入了2條新指令。

LOCK (加鎖)

UNLOCK (解鎖)

LOCK操作特性:只有一個(gè)線程能執(zhí)行成功!如果第一個(gè)線程執(zhí)行成功,第二個(gè)線程也嘗試LOCK,就會(huì)阻塞等待,直到第一個(gè)線程執(zhí)行UNLOCK 釋放鎖~

Java中關(guān)鍵字synchronized的使用方法詳解

通過(guò)LOCK和UNLOCK 就把 LOAD ADD SAVE 這三個(gè)指令,給打包成了一個(gè)原子的操作(中間不能被打斷,也不能被其他線程穿插)。

這里的加鎖也是保證原子性的核心操作,所以線程里的沒(méi)組指令就會(huì)順序執(zhí)行,不在穿插執(zhí)行,就保證了線程1執(zhí)行完之后再去執(zhí)行線程2。

舉個(gè)例子:

就好比張三和李四去ATM里去取錢(qián),當(dāng)張三進(jìn)去取錢(qián)時(shí),進(jìn)去后就會(huì)鎖門(mén),李四就會(huì)在外面等待,直到張三取完錢(qián)出來(lái)后,李四在進(jìn)去取錢(qián)。

synchronized 也會(huì)禁止編譯器進(jìn)行“內(nèi)存可見(jiàn)性”和“指令重排序”的優(yōu)化~ 同時(shí)程序運(yùn)行的效率就會(huì)降低,也會(huì)導(dǎo)致線程之間相互去等待,就涉及到系統(tǒng)的一些調(diào)度,也會(huì)引入一些時(shí)間成本。

synchronized修飾的對(duì)象有以下幾種:

修飾一個(gè)代碼塊,被修飾的代碼塊稱(chēng)為同步語(yǔ)句塊,其作用的范圍是大括號(hào){}括起來(lái)的代碼,作用的對(duì)象是調(diào)用這個(gè)代碼塊的對(duì)象;

public class TestDemo{ public void methond() {// 進(jìn)入代碼塊會(huì)鎖 this 指向?qū)ο笾械逆i;// 出代碼塊會(huì)釋放 this 指向的對(duì)象中的鎖synchronized (this) {} } public static void main(String[] args) {TestDemo demo = new TestDemo();demo.methond(); }}

修飾一個(gè)方法,被修飾的方法稱(chēng)為同步方法,其作用的范圍是整個(gè)方法,作用的對(duì)象是調(diào)用這個(gè)方法的對(duì)象;

public class TestDemo{ public synchronized void methond() { } public static void main(String[] args) {TestDemo demo = new TestDemo();demo.methond();// 進(jìn)入方法會(huì)鎖 demo 指向?qū)ο笾械逆i;// 出方法會(huì)釋放 demo 指向的對(duì)象中的鎖 }}

修改一個(gè)靜態(tài)的方法,其作用的范圍是整個(gè)靜態(tài)方法,作用的對(duì)象是這個(gè)類(lèi)的所有對(duì)象;

public class TestDemo{ public synchronized static void methond() { } public static void main(String[] args) {methond();// 進(jìn)入方法會(huì)鎖 TestDemo.class 指向?qū)ο笾械逆i;//出方法會(huì)釋放 TestDemo.class 指向的對(duì)象中的鎖 }}

修改一個(gè)類(lèi),其作用的范圍是synchronized后面括號(hào)括起來(lái)的部分,作用主的對(duì)象是這個(gè)類(lèi)的所有對(duì)象。

public class TestDemo{ public static void methond() {// 進(jìn)入代碼塊會(huì)鎖 TestDemo.class 指向?qū)ο笾械逆i;//出代碼塊會(huì)釋放 TestDemo.class 指向的對(duì)象中的鎖synchronized (TestDemo.class) {} } public static void main(String[] args) {TestDemo demo = new TestDemo();demo.methond(); }}

總結(jié):

無(wú)論synchronized關(guān)鍵字加在方法上還是對(duì)象上,如果它作用的對(duì)象是非靜態(tài)的,則它取得的鎖是對(duì)象; 如果synchronized作用的對(duì)象是一個(gè)靜態(tài)方法或一個(gè)類(lèi),則它取得的鎖是對(duì)類(lèi),該類(lèi)所有的對(duì)象同一把鎖。 每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián),誰(shuí)拿到這個(gè)鎖誰(shuí)就可以運(yùn)行它所控制的那段代碼。 實(shí)現(xiàn)同步是要很大的系統(tǒng)開(kāi)銷(xiāo)作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無(wú)謂的同步控制。

拓展:

public class TestDemo { static class Counter{public int count = 0; public void add(){ synchronized (this){ count++; }} } public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(){ @Override public void run() {for (int i = 0; i < 50000; i++) { synchronized (counter){counter.add(); }} }};Thread t2 = new Thread(){ @Override public void run() {for (int i = 0; i < 50000; i++) { synchronized (counter){counter.add(); }} }};//啟動(dòng)兩個(gè)線程t1.start();t2.start();//等待兩個(gè)線程結(jié)束t1.join();t2.join();System.out.println(counter.count); }}

此時(shí)可以看出上述代碼,加了兩次鎖,會(huì)發(fā)生什么呢?

Java中關(guān)鍵字synchronized的使用方法詳解

Java中關(guān)鍵字synchronized的使用方法詳解

但是運(yùn)行代碼發(fā)現(xiàn)程序依然正確運(yùn)行?? 為什么

但是上述分析死鎖的思路是對(duì)的

只是因?yàn)閟ynchronized內(nèi)部使用特殊手段來(lái)處理了這種情況 。

這樣的操作特性我們叫做 可重入鎖

synchronized 內(nèi)部記錄了當(dāng)前這把鎖是哪個(gè)線程持有的~

如果當(dāng)前加鎖線程和持有鎖的線程是同一個(gè)線程~

此時(shí)就并不是真的進(jìn)行“加鎖操作”,而是把一個(gè)計(jì)數(shù)器加一;

如果后續(xù)該線程繼續(xù)嘗試獲取鎖,繼續(xù)判定加鎖線程和持有鎖線程是不是同一個(gè)線程,只要是同一個(gè)線程,就不真的加鎖,而是計(jì)數(shù)器+1;

如果該線程調(diào)用解鎖操作,也不是立刻就解鎖,而是計(jì)數(shù)器減1

直到計(jì)數(shù)器減成0了,才認(rèn)為真的要“釋放鎖”,才允許其他線程來(lái)獲取鎖~~

總結(jié)

到此這篇關(guān)于Java中synchronized使用的文章就介紹到這了,更多相關(guān)Java中synchronized用法內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 欧美午夜视频在线观看 | 午夜免费观看网站 | av成人在线观看 | 国产精品成人一区二区 | 国内成人免费视频 | 青青草综合在线 | 日韩成人免费视频 | 亚洲激情在线 | 午夜视频一区二区三区 | 欧美在线国产 | 亚洲一二三| 91在线精品一区二区三区 | 日韩视频网站在线观看 | 一区二区三区影视 | www.在线播放 | 亚洲国产精品99久久久久久久久 | 在线播放一区二区三区 | 狠狠干狠狠操 | 亚洲成av人片一区二区梦乃 | 四虎影院最新网站 | 69日影院| 日韩中文字幕在线播放 | 久久在线 | 国产男女视频在线观看 | 欧美区 日韩区 | 欧美在线一区二区 | 少妇一区二区三区 | 亚洲免费在线观看 | 亚洲视频在线观看 | 91亚洲成人| 伊人一区二区三区 | 成人av免费在线 | 精品国产一区二区三区四区 | 在线观看国精产品二区1819 | 亚洲视频中文字幕 | 久久国产精品久久久久久 | 亚洲国产成人av好男人在线观看 | 中文字幕在线观看2021 | 久久成人一区 | 黄色天堂在线观看 | 狠狠狠干 |