1. 程式人生 > >JAVA多執行緒之Synchronized關鍵字--物件鎖的特點

JAVA多執行緒之Synchronized關鍵字--物件鎖的特點

一,介紹

本文介紹JAVA多執行緒中的synchronized關鍵字作為物件鎖的一些知識點。

所謂物件鎖,就是就是synchronized 給某個物件 加鎖。關於 物件鎖 可參考:這篇文章

二,分析

synchronized可以修飾例項方法,如下形式:

1 public class MyObject {
2 
3     synchronized public void methodA() {
4         //do something....
5     }

這裡,synchronized 關鍵字鎖住的是當前物件。這也是稱為物件鎖的原因。

為啥鎖住當前物件?因為 methodA()是個例項方法,要想執行methodA(),需要以 物件.方法() 的形式進行呼叫(obj.methodA(),obj是MyObject類的一個物件,synchronized就是把obj這個物件加鎖了)。

上面程式碼也可寫成這樣:

1 public class MyObject {
2 
3     public void methodA() {
4         synchronized(this){
5             //do something....
6         }
7     }

三,特點

使用synchronized關鍵字同步一個明顯的特點是:MyObject類中定義有多個synchronized修飾的例項方法時,若多個執行緒擁有同一個MyObject類的物件則這些方法只能以同步的方式執行。即,執行完一個synchronized修飾的方法後,才能執行另一個synchronized修飾的方法。

如下:

 1 public class MyObject {
 2 
 3     synchronized public void methodA() {
 4         //do something....
 5     }
 6 
 7     synchronized public void methodB() {
 8         //do some other thing
 9     }
10 }

MyObject類中有兩個synchronized修飾的方法。

 1 public class ThreadA extends Thread {
2 3 private MyObject object; 4 //省略構造方法 5 @Override 6 public void run() { 7 super.run(); 8 object.methodA(); 9 } 10 }

執行緒A執行methodA()

public class ThreadB extends Thread {

    private MyObject object;
//省略構造方法
    @Override
    public void run() {
        super.run();
        object.methodB();
    }
}

執行緒B執行methodB()

public class Run {
    public static void main(String[] args) {
        MyObject object = new MyObject();

        //執行緒A與執行緒B 持有的是同一個物件:object
        ThreadA a = new ThreadA(object);
        ThreadB b = new ThreadB(object);
        a.start();
        b.start();
    }
}

由於執行緒A和執行緒B持有同一個MyObject類的物件object,儘管這兩個執行緒需要呼叫不同的方法,但是必須是同步的,比如:執行緒B需要等待執行緒A執行完了methodA()方法之後,它才能執行methodB()方法。

四,結論

從上可以看出,本文中講述的 synchronized 鎖的範圍是整個物件。如果一個類中有多個synchronized修飾的同步方法,且多個執行緒持有該類的同一個物件(該類的相同的物件),儘管它們呼叫不同的方法,各個方法的執行也是同步的。

如果各個同步的方法之間沒有共享變數,或者說各個方法之間沒有聯絡,但也只能同步執行,這會影響效率。

五,應用--使用synchronized避免 因資料不一致性而導致讀髒資料的情況

如下示例:

 1 public class MyObject {
 2 
 3     private String userName = "b";
 4     private String passWord = "bb";
 5     
 6     synchronized public void methodA(String userName, String passWord) {
 7         this.userName = userName;
 8         try{
 9             Thread.sleep(5000);
10         }catch(InterruptedException e){
11             
12         }
13         this.passWord = passWord;
14     }
15 
16     synchronized public void methodB() {
17         System.out.println("userName" + userName + ": " + "passWord" + passWord);
18     }
19 }

methodA()負責更改使用者名稱和密碼。在現實中,一個使用者名稱對應著一個密碼。。。

methodB()負責讀取使用者名稱和密碼。

如果methodB()沒有用synchronized 修飾,執行緒A在呼叫methodA()執行到第7行,更改了使用者名稱,因某種原因(比如在第9行睡眠了)放棄了CPU。

此時,如果執行緒B去執行methodB(),那麼讀取到的使用者名稱是執行緒A更改了的使用者名稱("a"),但是密碼卻是原來的密碼("bb")。因為,執行緒A睡眠了,還沒有來得及更改密碼。

但是,如果methodB()用synchronized修飾,那麼執行緒B只能等待執行緒A執行完畢之後(即改了使用者名稱,也改了密碼),才能執行methodB讀取使用者名稱和密碼。因此,就避免了資料的不一致性而導致的髒讀問題。

其他參考資料:

相關推薦

JAVA執行Synchronized關鍵字--物件特點

一,介紹 本文介紹JAVA多執行緒中的synchronized關鍵字作為物件鎖的一些知識點。 所謂物件鎖,就是就是synchronized 給某個物件 加鎖。關於 物件鎖 可參考:這篇文章 二,分析 synchronized可以修飾例項方法,如下形式: 1 public class My

Java 執行synchronized關鍵字詳解

package com.example; /** * Created by 晁東洋 on 2017/5/27. */ public class MyThreadClass { public static void main(String args[]){ Exampletest

java執行synchronized和volatile關鍵字

synchronized同步方法 髒讀 在多個執行緒對同一個物件中的例項變數進行併發訪問的時候,取到的資料可能是被更改過的,稱之為“髒讀”,這就是非執行緒安全的。解決的方法為synchronized關鍵字進行同步,使之操作變成同步而非非同步。 public

Java執行Synchronized方式和CAS方式實現執行安全效能對比

效能比較猜想 1.大膽假設 在設計試驗方法之前,針對Synchronized和CAS兩種方式的特點,我們先來思考一下兩種方式效率如何? 首先,我們在回顧一下兩種方式是如何保證執行緒安全的。Synchronized方式通過大家應該很熟悉,他的行為非常悲觀,只要有一個執行緒進

java執行synchronized與lock、wait與notify

class Res { public String name; public String sex; public Boolean flag = false; public Lock lock = new ReentrantLock(); Condition condition = lock.new

java執行volatile關鍵字

在java執行緒併發處理中,關鍵字volatile的主要作用是使變數在多個執行緒間可見。那麼volatile到底該怎麼用了?我們首先來看一段程式碼: public class MyThread1 i

Java執行synchronized詳解

## 目錄 - synchronized簡介 - 同步的原理 - 物件頭與鎖的實現 - 鎖的優化與升級 - Monitor Record - 鎖的對比 ## synchronized簡介 `synchronized`關鍵字,一般稱之為“同步鎖”或者重量級鎖(JAVA SE 1.6之後引入了`偏向鎖`和`輕

java執行Lock--顯式

Lock與Synchronized簡介 Synchornized相信大家用的已經比較熟悉了,這裡我就不介紹它的用法了 Synchronized被稱為同步鎖或者是隱式鎖,隱式鎖與顯式鎖區別在於,隱式鎖的獲取和釋放都需要出現在一個塊結構中,而且是有順序的,獲取鎖的順序和釋放鎖的順序必須相反,就是說,

java執行(二)

一,鎖 在物件的建立時java會為每個object物件分配一個monitor( 監視器或者監視鎖),當某個物件的同步方法(synchronized methods )被多個執行緒呼叫時,該物件的monitor將負責處理這些訪問的併發獨佔要求。 當一個執行緒呼叫一個物件的同步方法時(sy

java執行3:關鍵字synchronized取得的都是物件,而不是把一段程式碼或者方法(函式)當作

java多執行緒3:關鍵字synchronized取得的鎖都是物件鎖,而不是把一段程式碼或者方法(函式)當作鎖 a.當多個執行緒訪問同一個物件的時候,哪個執行緒先執行帶synchronized關鍵字的方法,哪個執行緒就該方法所屬物件的鎖Lock,那麼其他物件就智慧呈等待狀態。但是如果多個執行緒訪

Java執行生產者消費者問題:使用synchronized 關鍵字解決生產者消費者問題

        今天看了一片博文,講Java多執行緒之執行緒的協作,其中作者用程式例項說明了生產者和消費者問題,但我及其他讀者發現程式多跑幾次還是會出現死鎖,百度搜了下大都數的例子也都存在bug,經過仔細研究發現其中的問題,並解決了,感覺有意義貼出來分享下。        

JAVA執行volatile 與 synchronized 的比較

一,volatile關鍵字的可見性 要想理解volatile關鍵字,得先了解下JAVA的記憶體模型,Java記憶體模型的抽象示意圖如下: 從圖中可以看出: ①每個執行緒都有一個自己的本地記憶體空間--執行緒棧空間???執行緒執行時,先把變數從主記憶體讀取到執行緒自己

java執行物件的併發訪問

1.synchronized同步方法 --1.1方法內的變數是執行緒安全的 解釋:由於方法內的變數是私有的,本體訪問的同時別人訪問不了,所以是執行緒安全的。 --1.2例項變數是非執行緒安全的 解釋:

Java執行記憶體可見性和原子性:Synchronized和Volatile的比較

在刷題時,碰到一題:關於volatile關鍵字的說法錯誤的是: A. 能保證執行緒安全 B volatile關鍵字用在多執行緒同步中,可保證讀取的可見性  C JVM保證從主記憶體載入到執行緒工做記憶體的值是最新的 D volatile能禁止指令進行指令重排序 答案:A 處

Java執行物件及變數的併發訪問

Java物件及變數的併發訪問 當多個執行緒同時對同一個物件中的例項變數進行併發訪問時可能會產生執行緒安全問題。產生的後果就是”髒讀”,即收到的資料其實是被更改過的。 如果訪問的是方法中的變數,則不存在”非執行緒安全”問題 可以通過以下幾種方式來解決,在對物

Java執行執行訪問共享物件和資料的方式

1.如果每個執行緒執行的程式碼相同,可以使用同一個Runable物件,這個Runable物件中有那個共享資料,例如賣票系統就可以這樣做。 package javaplay.test; public class MulteThreadShareData { publi

(實驗)Java一個執行synchronized巢狀物件時呼叫wait()只釋放wait函式關聯的所物件還是釋放所有物件

實驗是在JDK1.8下做的。 題目起的比較拗口,其實用程式碼說明起來更簡單,如下所示: public class MultiSynchronizedTest { private static Object lock1 = new Object(); p

Java執行Synchronized簡介和Static Synchronized的區別

在進行Java開發時,多執行緒的開發是經常會使用的。首先會問一個小問題啊,在Java中有幾種方法可以建立一個執行緒? 我給的答案是3種。(如果還有其他的請留言告訴我哈。) 1、建立直接繼承自Thread類建立執行緒子類。   步驟如下:a 定義一個子類,同時

Java執行join()方法

概要 本章,會對Thread中join()方法進行介紹。涉及到的內容包括: 1. join()介紹 2. join()原始碼分析(基於JDK1.7.0_40) 3. join()示例 來源:http://www.cnblogs.com/skywang12345/p/34792

白話理解java執行join()方法

join字面意思是加入,我理解為插隊. 舉例:媽媽在炒菜,發現沒喲醬油了,讓兒子去打醬油,兒子打完醬油,媽媽炒完菜,全家一起吃 package cn.yh.thread01; /** * * 打醬油的例子 */ public class Demo03 { public stat