1. 程式人生 > >012 內置鎖和synchronized

012 內置鎖和synchronized

color 任務 原子 解決問題 釋放 cep 調用 線程安全 失敗

一 . 概述

在前面我們說到線程安全性問題解決的核心就是同步,同步的核心就是保證原子性.

在java之中最早就支持語法層面的同步解決了,並且提供了synchronized的方式解決問題.


二 .內置鎖

  在java之中每一個對象都是一個內置鎖,這個在JVM的體系之中就規定好了.

  內置鎖的規定也就決定我們可以拿任意的對象進行同步操作.

內置鎖常常配合synchronized使用.


三 .synchronized

  該關鍵詞的作用是同步,需要配合內置鎖進行使用.

    常見的synchronized的使用方式有三種:

     [1]在靜態方法中使用

     [2]在實例方法中使用

     [3]在同步代碼塊之中使用

  其中: 在靜態方法之中的內置鎖是該類的class對象,實例方法的內置鎖是調用該方法的實例對象.

    在同步代碼塊之中的內置鎖需要顯示的指定.


四 . 例子

  將我們之前的計數代碼進行改寫,變成線程安全的操作. 

public class ProblemSolve {
    
    private int count = 0;
    
    public static void main(String[] args) throws Exception {
        ProblemSolve demo = new ProblemSolve();
        Thread t1 
= new Thread(new Runnable() { @Override public void run() { for(int x =0;x<10000;x++) { demo.add(); } } }); Thread t2 = new Thread(new Runnable() { @Override public
void run() { for(int x =0;x<10000;x++) { demo.add(); } } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("獲取最終的結果count : " + demo.count); } private synchronized void add() { count++; } }

我們所作出的概念僅僅是加上了一個synchronized關鍵詞就完成了同步的操作,這樣我們就能保證線程安全性.


五 .分析

  當我們的代碼進入同步代碼的時候,會試圖獲取內置鎖.

  獲取成功: 繼續運行

  獲取失敗: 進入該內置所的阻塞隊列.直到獲取該所的線程完成任務或者自己釋放內置所的擁有權.

        然後阻塞隊列的線程重新進入runnable狀態,再此嘗試獲取該鎖.

  以上就是synchronized同步的底層運行方式.


六. synchronized的優劣

  優勢 : 保證原子性,因為同步的代碼僅僅只有一個線程可以運行.

  劣勢: 粒度過大,獲取不到內置鎖的線程會進入阻塞隊列等待喚醒,這個是一刀切的方式,很有可能會影響性能.

解決: 在jak6之後,對synchronized關鍵詞的實現進行了優化,這個在下面會介紹.

012 內置鎖和synchronized