日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java的轻量锁,jvm第7节-锁(偏向锁,轻量锁,自旋锁)

發布時間:2024/9/30 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java的轻量锁,jvm第7节-锁(偏向锁,轻量锁,自旋锁) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在介紹鎖之前我們先介紹一個線程不安全的例子,一個全局的list,開2個線程往里面插入數據,代碼如下:

package com.jvm.day6.lock.demo;

import java.util.ArrayList;

import java.util.List;

/**

* 測試都線程共享一個變量帶來的現象

* @Author:xuehan

* @Date:2016年3月20日下午3:35:29

*/

class NumberAdd implements Runnable{

public static List numberList =new ArrayList();

public static int startNum;

public NumberAdd(int startNum){

this.startNum = startNum;

}

@Override

public void run() {

int count = 0;

while(count < 1000000){

numberList.add(count ++ );

startNum = startNum + 2;

}

}

}

public class Test{

public static void main(String[] args) throws Exception {

Thread t1 = new Thread(new NumberAdd(1));

Thread t2 = new Thread(new NumberAdd(0));

t1.start();

t2.start();

while(t1.isAlive() || t2.isAlive()){Thread.sleep(2);}

System.out.println("集合大小" + NumberAdd.numberList.size() );

System.out.println( "最后一個值的大" + NumberAdd.numberList.get(NumberAdd.numberList.size() - 1));

for(int i = NumberAdd.numberList.size() - 10 ; i < NumberAdd.numberList.size() -1; i ++){

System.out.println(NumberAdd.numberList.get(i));

}

}

}

按照開始想的,集合里面應該有200萬個數據了,結果卻出現了數組越界的錯誤,為什么呢,這是因為ArrayList不是線程安全的,用來存放數據的elementData是共享的, 線程A往list里添加數據的時候剛驗證大小通過,還沒有插入,然后輪到線程B執行,線程B剛好插入了list該擴容的最后一個元素,然后list滿了,線程A執行,A線程往集合里面插入元素,引起了數據越界。

jvm鎖

每個對象都一個mark頭,他的作用是:

Mark Word,對象頭的標記,32位

描述對象的hash、鎖信息,垃圾回收標記,年齡

指向鎖記錄的指針

指向monitor的指針

GC標記

偏向鎖線程ID

偏向鎖

jvm控制,可以設置jvm啟動參數

大部分情況是沒有競爭的,所以可以通過偏向來提高性能

所謂的偏向,就是偏心,即鎖會偏向于當前已經占有鎖的線程

將對象頭Mark的標記設置為偏向,并將線程ID寫入對象頭Mark

只要沒有競爭,獲得偏向鎖的線程,在將來進入同步塊,不需要做同步

當其他線程請求相同的鎖時,偏向模式結束

-XX:+UseBiasedLocking -jdk6需要手動打開

默認啟用

在競爭激烈的場合,偏向鎖會增加系統負擔

偏向鎖是系統自帶的設置參數開啟,java代碼如下:

package com.jvm.day6.lock;

import java.util.List;

import java.util.Vector;

/**

*使用 偏向鎖-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0

* 不使用偏向鎖-XX:-UseBiasedLocking

* 根據測試下面代碼使用偏向鎖可提高150毫秒執行時間 150/2300,提高效率6%

* @Author:xuehan

* @Date:2016年3月19日下午12:06:15

*/

public class DeflectionLock {

public static List numberList =new Vector();

public static void main(String[] args) throws InterruptedException {

System.out.println((int)'l');

long begin=System.currentTimeMillis();

int count=0;

int startnum=0;

while(count<10000000){

numberList.add(startnum);

startnum+=2;

count++;

}

long end=System.currentTimeMillis();

System.out.println(end-begin);

}

} ?根據我的寫實偏向鎖可以提高性能6%

輕量級鎖

BasicObjectLock,這個鎖是嵌入到線程棧中的,他有兩部組成

BasicLock和

ptr to obj hold the lock,

BasicLock里面存放著對象頭,

ptr to obj hold the lock為指向持有對象鎖的指針

普通的鎖處理性能不夠理想,輕量級鎖是一種快速的鎖定方法。

如果對象沒有被鎖定

將對象頭的Mark指針保存到鎖對象中

將對象頭設置為指向鎖的指針(在線程棧空間中)

如果輕量級鎖失敗,表示存在競爭,升級為重量級鎖(常規鎖)

在沒有鎖競爭的前提下,減少傳統鎖使用OS互斥量產生的性能損耗

在競爭激烈時,輕量級鎖會多做很多額外操作,導致性能下降

自旋鎖

當競爭存在時,如果線程可以很快獲得鎖,那么可以不在OS層掛起線程,讓線程做幾個空操作(自旋)

JDK1.6中-XX:+UseSpinning開啟

JDK1.7中,去掉此參數,改為內置實現

如果同步塊很長,自旋失敗,會降低系統性能

如果同步塊很短,自旋成功,節省線程掛起切換時間,提升系統性能

上面的一些鎖不是Java語言層面的鎖優化方法

他們是內置于JVM中的獲取鎖的優化方法和獲取鎖的步驟

偏向鎖可用會先嘗試偏向鎖

輕量級鎖可用會先嘗試輕量級鎖

以上都失敗,嘗試自旋鎖

再失敗,嘗試普通鎖,使用OS互斥量在操作系統層掛起

我們可以從以下方面對鎖進行優化

減少鎖的時間

沒必須放在同步塊的代碼盡量不要放在代碼塊里

減少鎖的粒度

將大對象,拆成小對象,大大增加并行度,降低鎖競爭

偏向鎖,輕量級鎖成功率提高

實現的例子如ConcurrentHashMap

使用若干個Segment :Segment[] segments

Segment中維護HashEntry

put操作時

先定位到Segment,鎖定一個Segment,執行put

在減小鎖粒度后, ConcurrentHashMap允許若干個線程同時進入

鎖分離

根據功能進行鎖分離

ReadWriteLock

讀多寫少的情況,可以提高性能

讀寫分離思想可以延伸,只要操作互不影響,鎖就可以分離

LinkedBlockingQueue

隊列

鏈表

鎖粗化

通常情況下,為了保證多線程間的有效并發,會要求每個線程持有鎖的時間盡量短,即在使用完公共資源后,應該立即釋放鎖。只有這樣,等待在這個鎖上的其他線程才能盡早的獲得資源執行任務。但是,凡事都有一個度,如果對同一個鎖不停的進行請求、同步和釋放,其本身也會消耗系統寶貴的資源,反而不利于性能的優化

for(int i=0;i<1000;i++){

synchronized(lock){}

}

// 應該寫成

synchronized(lock){

for(int i =0; i < 1000; i ++){}

}

這時候我們要增加鎖的持有時間不要讓請求和釋放鎖頻繁的發生

鎖消除

在java方法體里如果不是共享的變量不需要同步操作的,這時候jvm會自動的優化把鎖去掉,如StingBuffer和Vector,使用鎖消除

-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks

關閉鎖消除

-server -XX:+DoEscapeAnalysis -XX:-EliminateLocks

無鎖

鎖是悲觀的操作

無鎖是樂觀的操作

無鎖的一種實現方式

CAS(Compare And Swap),CAS是原子的

非阻塞的同步

CAS(V,E,N)

在應用層面判斷多線程的干擾,如果有干擾,則通知線程重試,一般這樣做會讓程序變的復雜,但性能更加好。

總結

以上是生活随笔為你收集整理的java的轻量锁,jvm第7节-锁(偏向锁,轻量锁,自旋锁)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。