java concurrent之前戲synchronized

對于多線程共享資源的情況須要進行同步,以避免一個線程的修改被還有一個線程的修改所覆蓋。

最普遍的同步方式就是synchronized。

把代碼聲明為synchronized。有兩個重要后果,一般是指該代碼具有 原子性(atomicity)和 可見性(visibility)。

1、原子性強調的是運行。意味著個時刻,僅僅有一個線程可以運行一段代碼,這段代碼通過一個monitor object保護。從而防止多個線程在更新共享狀態時相互沖突。

2、可見性強調的是結果。它要對付內存緩存和編譯器優化的各種反常行為。它必須確保釋放鎖之前對共享數據做出的更改對于隨后獲得該鎖的還有一個線程是可見的。

同步方法

看一個樣例就明確了:
import java.util.Random;

public class TestSyncClass {
?private int num=0;
?
?private Random random=new Random();
?
?public synchronized void testAdd1(){
??System.out.println("testAdd1--->>");
??num++;
??try {
???Thread.sleep(1000);
??} catch (InterruptedException e) {
???e.printStackTrace();
??}
??System.out.println("1-result-->>"+num);
?}
?
?public synchronized void testAdd2(){
??System.out.println("testAdd2--->>");
??num++;
??try {
???Thread.sleep(1000);
??} catch (InterruptedException e) {
???e.printStackTrace();
??}
??System.out.println("2-result-->>"+num);
?}
?
?public? void testAdd3(){
??System.out.println("testAdd3--->>");
??num++;
??try {
???Thread.sleep(1000);
??} catch (InterruptedException e) {
???e.printStackTrace();
??}
??System.out.println("3-result-->>"+num);
?}
?
?public static void main(String[] args) {
??final TestSyncClass syncClass=new TestSyncClass();
??Thread thread1=new Thread(){
???@Override
???public void run() {
????syncClass.testAdd1();
????super.run();
???}
??};
??
??Thread thread2=new Thread(){
???@Override
???public void run() {
????syncClass.testAdd2();
????super.run();
???}
??};
??
??Thread thread3=new Thread(){
???@Override
???public void run() {
????syncClass.testAdd3();
????super.run();
???}
??};
??
??thread1.start();
??thread2.start();
??thread3.start();
?}

}

代碼執行結果:
testAdd1--->>
testAdd3--->>
1-result-->>2
3-result-->>2
testAdd2--->>
2-result-->>3

代碼中testAdd1、testAdd2是被synchronized聲明的方法。testAdd3沒有聲明。在執行的時候因為testAdd3沒有被聲明,所以在緊跟著開始執行testAdd1的時候也執行了testAdd3。結果testAdd1執行的結果被testAdd3的結果覆蓋了,打印了同樣的值3。這個主要是可見性的問題。因為testAdd2也是被聲明過的,所以testAdd2并沒有馬上執行。而是等testAdd1執行完之后才開始執行。

全部對象都自己主動含有單一的鎖(也稱為監視器monitor object)。

當在對象上調用其隨意synchronized方法的時候,此對象都被加鎖。這時該對象上的其它synchronized方法僅僅有等到前一個方法調用完成并釋放了鎖之后才干被調用。

針對每一個類,也有一個鎖(作為類的Class對象的一部分)。所以synchronized static 方法能夠在類的范圍內防止對static數據的并發訪問。

同步塊

不管何種情況,要想鎖住代碼,必須使用同樣的鎖。比如把testAdd2改成
??????? private Object object=new Object();
?public void testAdd2(){
??synchronized(object){
???System.out.println("testAdd2--->>");
???num++;
???try {
????Thread.sleep(1000);
???} catch (InterruptedException e) {
????e.printStackTrace();
???}
???System.out.println("2-result-->>"+num);
??}
?}
則testAdd2和testAdd1就不會相互等待了。結果例如以下:
testAdd2--->>
testAdd3--->>
testAdd1--->>
3-result-->>3
2-result-->>3
1-result-->>3

事實上synchronized(object)是更安全的上鎖方式。由于直接聲明方法的形式用的是類的鎖,而聲明代碼塊的形式用的是私有屬性的鎖,尤其是在server開發的時候,外面類的鎖非常easy被黑客獲取。從而獲取了攻擊server的入口,而私有屬性的私有性讓黑客難以獲取,所以它的鎖就相對安全的多。

類同步

上面的main方法的三個線程用的是同一個TestSyncClass syncClass對象。假設每一個線程都各自創建一個對象就不能達到鎖定代碼的目標了。要想達到同步的目的,代碼須要改動成例如以下:

import java.util.Random;

public class TestSyncClass {
?private int num = 0;

?private static Object object = new Object();

?private Random random = new Random();

?public void testAdd1() {
??synchronized (object) {
???System.out.println("testAdd1--->>");
???num++;
???try {
????Thread.sleep(1000);
???} catch (InterruptedException e) {
????e.printStackTrace();
???}
???System.out.println("1-result-->>" + num);
??}
?}

?public void testAdd2() {
??synchronized (object) {
???System.out.println("testAdd2--->>");
???num++;
???try {
????Thread.sleep(1000);
???} catch (InterruptedException e) {
????e.printStackTrace();
???}
???System.out.println("2-result-->>" + num);
??}
?}

?public void testAdd3() {
??System.out.println("testAdd3--->>");
??num++;
??try {
???Thread.sleep(1000);
??} catch (InterruptedException e) {
???e.printStackTrace();
??}
??System.out.println("3-result-->>" + num);
?}

?public static void main(String[] args) {
??Thread thread1 = new Thread() {
???@Override
???public void run() {
????TestSyncClass syncClass = new TestSyncClass();
????syncClass.testAdd1();
????super.run();
???}
??};

??Thread thread2 = new Thread() {
???@Override
???public void run() {
????TestSyncClass syncClass = new TestSyncClass();
????syncClass.testAdd2();
????super.run();
???}
??};

??Thread thread3 = new Thread() {
???@Override
???public void run() {
????TestSyncClass syncClass = new TestSyncClass();
????syncClass.testAdd3();
????super.run();
???}
??};

??thread1.start();
??thread2.start();
??thread3.start();
?}

}

執行結果:

testAdd1--->>
testAdd3--->>
3-result-->>1
1-result-->>1
testAdd2--->>
2-result-->>1

事實上使用synchronized (TestSyncClass.class)類的鎖也能達到類似的效果,可是考慮到私有屬性的安全性就直接使用上面代碼做實例了。

注意:synchronized是不能繼承的,父類中synchronized的聲明在子類的繼承過程中須要再次聲明,否則synchronized將會丟失。

wait(), notify()。notifyAll()

基類不光有鎖。還有這三個方法。wait()會讓獲取鎖的線程等待并釋放鎖,直到notify()或notifyAll()喚醒并又一次獲取鎖。

先看一個樣例:
public class TestSyncClass {
?private int num = 0;

?private Object object = new Object();

?private Object object1 = new Object();

?public? void testAdd(int index) {
??System.out.println("testAdd" + index + "--->>");
??synchronized (object) {
???num++;
???try {
????object.wait();
???} catch (InterruptedException e) {
????e.printStackTrace();
???}
???System.out.println(index + "-result-->>" + num);
??}
?}

?public void release() {
??synchronized (object) {
???object.notifyAll();
???System.out.println("-release-->>");
??}
?}

?public static void main(String[] args) {
??final TestSyncClass syncClass = new TestSyncClass();
??Thread thread1 = new Thread() {
???@Override
???public void run() {
????syncClass.testAdd(1);
????super.run();
???}
??};

??Thread thread2 = new Thread() {
???@Override
???public void run() {
????syncClass.testAdd(2);
????super.run();
???}
??};

??Thread thread3 = new Thread() {
???@Override
???public void run() {
????syncClass.testAdd(3);
????super.run();
???}
??};

??thread1.start();
??thread2.start();
??thread3.start();

??Thread thread4 = new Thread() {
???@Override
???public void run() {
????try {
?????Thread.sleep(2000);
????} catch (InterruptedException e) {
?????e.printStackTrace();
????}
????syncClass.release();
????super.run();
???}
??};
??thread4.start();
?}

}

執行結果:
testAdd1--->>
testAdd2--->>
testAdd3--->>
-release-->>
3-result-->>3
2-result-->>3
1-result-->>3

調用object的wait(), notify()。notifyAll()法前,必須獲得object鎖,也就是這三個方法必須寫在synchronized(obj) {…} 代碼段內。否則跑出異常java.lang.IllegalMonitorStateException。


調用object.wait()后。線程A就釋放了object的鎖,否則syncClass.release()無法獲得object鎖,等待的線程。


當object.wait()方法返回后。各個線程須要再次獲得object鎖,才干繼續運行。
notify()僅僅能喚醒線程,notifyAll()則能所有喚醒,可是個線程須要又一次競爭object的鎖。

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285717.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285717.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285717.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開源項目【zheng】搭建流程

2019獨角獸企業重金招聘Python工程師標準>>> 搭建過程 項目地址 https://gitee.com/shuzheng/zheng這兩篇寫的比較詳細的搭建過程,結合一下就沒什么問題了。 https://my.oschina.net/yzuzhang/blog/1538555http://www.jianshu.com/p/b2fb42e17b581.JDK 1…

簡述HTML DOM及其節點分類

在JavaScript中,document這個對象大家一定很熟悉,哪怕是剛剛開始學習的新人,也會很快接觸到這個對象。而document對象不僅僅是一個普通的JavaScript內置對象,它還是一個巨大API的核心對象,這個巨大的API就是DOM&#x…

【CC精品教程】任務二:導入像控點、差分POS,空三平差權重設置,提交自由空三

《無人機航空攝影測量精品教程》合集目錄(Pix4d、CC、EPS、PhotoScan、Inpho) 【CC精品教程】任務一:CC新建工程、添加照片、相機參數設置、選擇坐標系統 本任務接著上一個任務,繼續完成CC項目作業,主要內容有:導入像控點、選擇空間參考系統,導入差分POS,空三平差權重設…

[轉]如何進行單元測試

一、單元測試步驟 代碼編寫完成后的單元測試工作主要分為兩個步驟: 人工靜態檢查 人工靜態檢查是測試的第一步,這個階段工作主要是保證代碼算法的邏輯正確性(盡量通過人工檢查發現代碼的邏輯錯誤)、清晰性、規范性、一致性、算法…

WPF 基礎控件之 TabControl樣式

其他基礎控件1.Window2.Button3.CheckBox4.ComboBox5.DataGrid 6.DatePicker7.Expander8.GroupBox9.ListBox10.ListView11.Menu12.PasswordBox13.TextBox14.RadioButton15.ToggleButton16.Slider 17.TreeView TabControl 實現下面的效果1)TabControl來實現動畫&…

開發團隊測試的難與易

做了多年的研發工程師,在所處的環境中,所接觸的開發人員中很少有看重對自己代碼進行測試這項工作的。大多研發人員往往是寫好了代碼運行起來,簡單做下測試,甚至不去測試就拋給接口使用者或者質量管理人員。而且理由很充分“沒時間…

C語言試題八十八之實現選冒泡排序算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 C語言實現冒…

兩個數值交換位置

2019獨角獸企業重金招聘Python工程師標準>>> 先說非計算機專業都能理解的。 int a 10; int b 20; 方法一: int c a; a b; b c; System.out.println("a"a",b"b); 方法二: a a b; b a - b; a a - b; System.out…

教你如何在Android 6.0上創建系統懸浮窗

郭霖大神的文章:http://mp.weixin.qq.com/s?__bizMzA5MzI3NjE2MA&mid2650235949&idx1&sn0f7eded67f834d38b02f8872768cb68a&scene0#wechat_redirect今天周二,又該跟大家分享由我執筆的文章了。從之前我寫的deep links、通知欄微技巧這兩篇文章中&a…

【CC精品教程】任務三:CC刺像控點,提交空三,新建重建項目(三維格網、三維點云、DOM和DSM)

《無人機航空攝影測量精品教程》合集目錄(Pix4d、CC、EPS、PhotoScan、Inpho) 【CC精品教程】任務一:CC新建工程、添加照片、相機參數設置、選擇坐標系統 【CC精品教程】任務二:導入像控點、差分POS,空三平差權重設置,提交自由空三 主要任務是準確的刺像控點,提交空三,…

官宣.NET 7 預覽版5

點擊上方藍字關注我們(本文閱讀時間:12分鐘)今天我們發布了 .NET 7 預覽版 5。.NET 7 的這個預覽版包括對通用數學的改進,方便了 API 作者,使其更輕松,一個新的 ML.NET 文本分類 API,增加了最先進的深度學習…

[轉]Android產品研發(十九)

轉載請標明出處:一片楓葉的專欄 上一篇文章中我們講解了webview中問題集錦,講解了webview的性能優化、webview種入Cookie信息、activity退出的時候清除webview信息報錯、如何通過java代碼和js代碼相互交互、webview如何下載文件以及騰訊的X5瀏覽服務等知…

C語言試題八十九之實現插入排序算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 C語言實現現…

【CC精品教程】ContextCapture 10.17安裝教程(附CC10.17安裝包下載)

《無人機航空攝影測量精品教程》合集目錄(Pix4d、CC、EPS、PhotoScan、Inpho) CC10.17相比之前的版本有了好的新的功能和優點,在傾斜攝影測量中有了更多的優勢,精度和運行速度有了很大的提升。本文講解CC的安裝,附CC10.17安裝包下載,是您航測傾斜攝影測量的入門必備。 文…

centos7 kickstart 使用小結

1、添加參數使網卡名稱變為eth 1bootloader --locationmbr --append"net.ifnames0 biosdevname0 rhgb quiet" 2、psize使用說明:修改vg PE16m 默認4m 支持256G磁盤,適當的調整pesize,可以更多的使用磁盤空間 1volgroup Vol1--pesize16384 pv.…

IOS-網絡(文件上傳)

1 //2 // ViewController.m3 // IOS_0206_文件上傳4 //5 // Created by ma c on 16/2/6.6 // Copyright © 2016年 博文科技. All rights reserved.7 //8 9 #import "ViewController.h"10 #define BWFileBoundary "----------BowenKeJi"11 #define…

mac SecureCRT設置

參考: http://www.2cto.com/os/201407/320292.html SecureCRT 設置 1)每次登陸都要輸入密碼: Global Option -> General 取消:Use Keychain前面的勾 2)Logon Actions Logon Actions很強大,和python里…

【微服務專題之】.Net6下集成消息隊列上-RabbitMQ

微信公眾號:趣編程ACE關注可了解更多的.NET日常實戰開發技巧,如需源碼 請公眾號后臺留言 源碼;[如果覺得本公眾號對您有幫助,歡迎關注].Net中RabbitMQ的使用超清觀看視頻哦~官網鏈接RabbitMQ代碼演示-詳細見代碼注釋,操作看上文視…

[轉]總結:Apache/Tomcat/JBOSS/Jetty/Nginx區別 .

總結:Apache/Tomcat/JBOSS/Nginx區別 . 1、Apache是Web服務器,Tomcat是應用(Java)服務器。Tomcat在中小型系統和并發訪問用戶不是很多的場合下被普遍使用。Apache支持靜態頁,Tomcat支持動態的。 2、Jetty:Tomcat內核作…

華為云GaussDB,11.11讓企業無后顧之憂

每年11.11大促對于數據庫而言都是一場生死考驗,如何保障系統的穩定可靠,如何平穩度過業務流量洪峰期,如何高效擴容,成為每個參與活動客戶的一大痛點。本文將通過5個常見的大促問題及分析,看看華為云GaussDB是如何解決這…