Java final, static, native, volatile, synchronized 關鍵字詳解

final 關鍵字

含義: 最終的,不可被改變的
用途: 用於修飾類、方法、屬性和變量。
特性:

  1. 用final修飾類時,被修飾的類不可以被繼承。final類中的所有成員方法都會被隱式地指定爲final方法。
  2. 用final修飾方法時,被修飾的方法不能被重寫。在早期的Java版本中被final修飾的方法會轉爲內嵌調用從而提升性能。(注:類的private方法會隱式地被指定爲final方法。)
  3. 用fina修飾的變量,如果是基本數據類型的變量,則其數值一旦在初始化之後便不能更改;如果是引用類型的變量,則在對其初始化之後便不能再讓其指向另一個對象。(注:用fianl修飾的類屬性變量必須進行初始化(包括在構造方法中初始化))

static 關鍵字

含義: 靜態的,全局的
用途: 用於修飾類、方法、變量和代碼塊。
描述: static關鍵字表示靜態的,全局的可以用來修飾類、方法、變量和代碼塊。在通常的開發中最常見的是用static修飾的成員變量和成員方法,被static修飾的成員變量和成員方法獨立於該類的任何對象。也就是說,它不依賴類特定的實例,被類的所有實例共享。只要這個類被加載,Java虛擬機就能根據類名在運行時數據區的方法區內定找到他們。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象,可以通過類名加“.”進行直接訪問。
無論是變量,方法,還是代碼塊,只要用static修飾,就是在類被加載時就已經"準備好了",也就是可以被使用或者已經被執行,都可以脫離對象而執行。反之,如果沒有static,則必須要依賴於對象實例。

特性:

  1. 如果一個類要被聲明爲static的,只有一種情況,就是靜態內部類。靜態內部類可以聲明普通成員變量和方法,而普通內部類不能聲明static成員變量和方法。
  2. 用static修飾的代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,它不在任何的方法體內,可以有多個,位置可以隨便放,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先後順序依次執行它們,每個代碼塊只會被執行一次。
  3. 用static修飾的方法,只能調用static變量和static方法,不能以任何形式引用this和super,是抽象方法abstract
  4. 用static修飾的變量,在定義時必須要進行初始化,且初始化時間要早於非靜態變量。

native 關鍵字

含義: 原生的,本地的
用途: 用於修飾方法
描述: native關鍵字用來修飾方法。被native關鍵字修飾的方法是一個原生態方法,方法對應的實現不是在當前文件,而是在用其他語言(如C和C++)實現的文件中。Java不是完美的,Java的不足除了體現在運行速度上要比傳統的C++慢許多之外,Java語言本身不能對操作系統底層進行訪問和操作(如系統硬件等),爲此Java使用native方法來擴展Java程序的功能,通過JNI接口調用其他語言來實現對底層的訪問。

volatile 關鍵字

含義: 易變的,不穩定的
用途: 用於修飾變量
描述: Java 語言中用 volatile 修飾的變量通常是爲了保證不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是立即可見的。volatile是Java提供的一種輕量級的同步機制,在併發編程中,它也扮演着比較重要的角色,可以被看作是一種 “程度較輕的 synchronized ”。與 synchronized 塊相比,volatile 變量所需的編碼較少,並且運行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分。

特性:

  1. 保證內存可見。 當一個共享變量被 volatile 修飾時,它會保證修改的值會立即被更新到主存,當有其他線程需要讀取時,它會去主存中讀取新值。也就是每次取值在都會取內存中的值,每次更新都會立即更新主存中的值。

  2. 禁止指令重排。 volatile 關鍵字能禁止指令重排序,所以 volatile 能在一定程度上保證有序性。volatile 關鍵字禁止指令重排序有兩層意思,1)當程序執行到 volatile 變量的讀操作或者寫操作時,在其前面的操作的更改肯定全部已經進行,且結果已經對後面的操作可見,在其後面的操作肯定還沒有進行;2)在進行指令優化時,不能將在對 volatile 變量訪問的語句放在其後面執行,也不能把 volatile 變量後面的語句放到其前面執行。

注意:

  1. volatile 無法保證對變量的任何操作都是原子性,可以採用 synchronized,Lock 或用java.util.concurrent.atomic 包下提供了一些原子操作類來保證操作的原子性。

參考博客: Java併發編程:volatile關鍵字解析

synchronized 關鍵字

含義: 同步,在時間上一致,同速進行
用途: 用於修飾方法和代碼塊。
描述: Java 語言中用 synchronized 修飾方法和代碼塊來控制在同一時刻只有一個線程執行該段代碼,從而保證多併發情況下的數據安全。簡單講 synchronized 就是給修飾的方法或代碼塊聲明一個鎖,擁有這個鎖的線程可以執行區塊裏面的指令,其他的線程只能等待獲取鎖,然後才能執行相同的操作。用synchronized 修飾方法和代碼塊通常被稱爲“加鎖”。

特性:

  1. 類鎖: 當 synchronized 修飾靜態方法或 synchronized 修飾代碼塊時傳入某個class對象(synchronized (XXXX.class))時被稱爲類鎖。某個線程得到了一個類鎖之後,其他所有被該類鎖加鎖方法或代碼塊是鎖定的, 其他線程是無法訪問的,但是其他線程還是可以訪問沒有被該類鎖加鎖的任何代碼。

  2. 對象鎖: 當 synchronized 修飾非靜態方法或 synchronized 修飾代碼塊時傳入非class對象(synchronized this))時被稱爲對象鎖。某個線程得到了對象鎖之後,該對象的其他被 synchronized修飾的方法(同步方法)是鎖定的,其他線程是無法訪問的。但是其他線程還是可以訪問沒有進行同步的方法或者代碼;當獲取到與對象關聯的內置鎖時,並不能阻止其他線程訪問該對象,當某個線程獲得對象的鎖之後,只能阻止其他線程獲得同一個鎖。

  3. 類鎖和對象鎖的關係: 如同每個類只有一個class對象而類的實例可以有很多個一樣,每個類只有一個類鎖,每個實例都有自己的對象鎖,所以不同對象實例的對象鎖是互不干擾的。但是有一點必須注意的是,其實類鎖只是一個概念上的東西,並不是真實存在的,它只是用來幫助我們理解鎖定實例方法和靜態方法的區別的。類鎖和對象鎖是不一樣的鎖,是互相獨立的,兩者不存在競爭關係,線程獲得對象鎖的同時,也可以獲得該類鎖,即同時獲得兩個鎖,這是允許的。

  4. 其他特性: 因爲被 synchronized 修飾的代碼在同一時刻只有一個線程執行,所以也就保證了操作的原子性和內存可見性。

總結: synchronized 的本質就是給一段代碼加個鎖,來保證同一時刻只有一個線程執行該段代碼。所以不管是類鎖還是對象鎖,被加鎖了的代碼,每個線程只有獲取了對應的鎖之後才能執行,未加鎖的代碼任何情況下都能立即執行。

參考資料: 百度百科:synchronized

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章