亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

JAVA中的鎖機制

2019-11-06 06:40:49
字體:
來源:轉載
供稿:網友

鎖作為并發共享數據,保證一致性的工具,在java平臺有多種實現(如 synchronized 和 ReentrantLock等等 ) 。java平臺下的鎖如下所示:

1、自旋鎖2、自旋鎖的其他種類3、阻塞鎖4、可重入鎖5、讀寫鎖6、互斥鎖7、悲觀鎖8、樂觀鎖9、公平鎖10、非公平鎖11、偏向鎖12、對象鎖13、線程鎖14、鎖粗化15、輕量級鎖16、鎖消除17、鎖膨脹18、信號量

1、自旋鎖

自旋鎖是采用讓當前線程不停地的在循環體內執行實現的,當循環的條件被其他線程改變時 才能進入臨界區。如下

public class SpinLock {  PRivate AtomicReference<Thread> sign =new AtomicReference<>();  public void lock(){    Thread current = Thread.currentThread();    while(!sign .compareAndSet(null, current)){    }  }  public void unlock (){    Thread current = Thread.currentThread();    sign .compareAndSet(current, null);  }}

使用了CAS原子操作,lock函數將owner設置為當前線程,并且預測原來的值為空。unlock函數將owner設置為null,并且預測值為當前線程。

當有第二個線程調用lock操作時由于owner值不為空,導致循環一直被執行,直至第一個線程調用unlock函數將owner設置為null,第二個線程才能進入臨界區。

由于自旋鎖只是將當前線程不停地執行循環體,不進行線程狀態的改變,所以響應速度更快。但當線程數不停增加時,性能下降明顯,因為每個線程都需要執行,占用CPU時間。如果線程競爭不激烈,并且保持鎖的時間段。適合使用自旋鎖。

注:該例子為非公平鎖,獲得鎖的先后順序,不會按照進入lock的先后順序進行。

2.自旋鎖的其他種類

在自旋鎖中 另有三種常見的鎖形式:TicketLock ,CLHlock 和MCSlock

Ticket鎖主要解決的是訪問順序的問題,主要的問題是在多核cpu上

import java.util.concurrent.atomic.AtomicInteger;public class TicketLock {    private AtomicInteger serviceNum = new AtomicInteger();    private AtomicInteger ticketNum = new AtomicInteger();    private static final ThreadLocal<Integer> LOCAL= new ThreadLocal<Integer>();    public void lock() {        int myticket = ticketNum.getAndIncrement();        LOCAL.set(myticket);        while (myticket != serviceNum.get()) {        }    }    public void unlock() {        int myticket = LOCAL.get();        serviceNum.compareAndSet(myticket, myticket + 1);    }}每次都要查詢一個serviceNum 服務號,影響性能(必須要到主內存讀取,并阻止其他cpu修改)。

CLHLock 和MCSLock 則是兩種類型相似的公平鎖,采用鏈表的形式進行排序,

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;public class CLHLock {    public static class CLHNode {        private volatile boolean isLocked = true;    }    @SuppressWarnings("unused")    private volatile CLHNode tail;    private static final ThreadLocal<CLHNode>  LOCAL   = new ThreadLocal<CLHNode>();    private static final AtomicReferenceFieldUpdater<CLHLock, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock.class,CLHNode.class, "tail");    public void lock() {        CLHNode node = new CLHNode();        LOCAL.set(node);        CLHNode preNode = UPDATER.getAndSet(this, node);        if (preNode != null) {            while (preNode.isLocked) {            }            preNode = null;            LOCAL.set(node);        }    }    public void unlock() {        CLHNode node = LOCAL.get();        if (!UPDATER.compareAndSet(this, node, null)) {            node.isLocked = false;        }        node = null;    }}

CLHlock是不停的查詢前驅變量, 導致不適合在NUMA 架構下使用(在這種結構下,每個線程分布在不同的物理內存區域)

MCSLock則是對本地變量的節點進行循環。不存在CLHlock 的問題。

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;public class MCSLock {    public static class MCSNode {        volatile MCSNode next;        volatile boolean isLocked = true;    }private static final ThreadLocal<MCSNode> NODE = new ThreadLocal<MCSNode>();    @SuppressWarnings("unused")    private volatile MCSNode queue;    private static final AtomicReferenceFieldUpdater<MCSLock, MCSNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(MCSLock.class, MCSNode.class, "queue");    public void lock() {        MCSNode currentNode = new MCSNode();        NODE.set(currentNode);        MCSNode preNode = UPDATER.getAndSet(this, currentNode);        if (preNode != null) {            preNode.next = currentNode;            while (currentNode.isLocked) {            }        }    }    public void unlock() {        MCSNode currentNode = NODE.get();        if (currentNode.next == null) {            if (UPDATER.compareAndSet(this, currentNode, null)) {            } else {                while (currentNode.next == null) {                }            }        } else {            currentNode.next.isLocked = false;            currentNode.next = null;        }    }}

從代碼上 看,CLH 要比 MCS 更簡單,

CLH 的隊列是隱式的隊列,沒有真實的后繼結點屬性。

MCS 的隊列是顯式的隊列,有真實的后繼結點屬性。

JUC ReentrantLock 默認內部使用的鎖 即是 CLH鎖(有很多改進的地方,將自旋鎖換成了阻塞鎖等等)。

三、阻塞鎖:

阻塞鎖,與自旋鎖不同,改變了線程的運行狀態。在JAVA環境中,線程Thread有如下幾個狀態:

1,新建狀態

2,就緒狀態

3,運行狀態

4,阻塞狀態

5,死亡狀態

阻塞鎖,可以說是讓線程進入阻塞狀態進行等待,當獲得相應的信號(喚醒,時間) 時,才可以進入線程的準備就緒狀態,準備就緒狀態的所有線程,通過競爭,進入運行狀態。JAVA中,能夠進入/退出、阻塞狀態或包含阻塞鎖的方法有 ,synchronized 關鍵字(其中的重量鎖),ReentrantLock,Object.wait()/notify(),LockSupport.park()/unpart()(j.u.c經常使用)

下面是一個JAVA 阻塞鎖實例

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;import java.util.concurrent.locks.LockSupport;public class CLHLock1 {    public static class CLHNode {        private volatile Thread isLocked;    }    @SuppressWarnings("unused")    private volatile CLHNode tail;    private static final ThreadLocal<CLHNode> LOCAL   = new ThreadLocal<CLHNode>();    private static final AtomicReferenceFieldUpdater<CLHLock1, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock1.class,CLHNode.class, "tail");    public void lock() {        CLHNode node = new CLHNode();        LOCAL.set(node);        CLHNode preNode = UPDATER.getAndSet(this, node);        if (preNode != null) {            preNode.isLocked = Thread.currentThread();            LockSupport.park(this);            preNode = null;            LOCAL.set(node);        }    }    public void unlock() {        CLHNode node = LOCAL.get();        if (!UPDATER.compareAndSet(this, node, null)) {            System.out.println("unlock/t" + node.isLocked.getName());            LockSupport.unpark(node.isLocked);        }        node = null;    }}

在這里我們使用了LockSupport.unpark()的阻塞鎖。 該例子是將CLH鎖修改而成。

阻塞鎖的優勢在于,阻塞的線程不會占用cpu時間, 不會導致 CPu占用率過高,但進入時間以及恢復時間都要比自旋鎖略慢。

在競爭激烈的情況下 阻塞鎖的性能要明顯高于 自旋鎖。

理想的情況則是; 在線程競爭不激烈的情況下,使用自旋鎖,競爭激烈的情況下使用,阻塞鎖。

四、可重入鎖:

本文里面講的是廣義上的可重入鎖,而不是單指JAVA下的ReentrantLock。

可重入鎖,也叫做遞歸鎖,指的是同一線程 外層函數獲得鎖之后 ,內層遞歸函數仍然有獲取該鎖的代碼,但不受影響。在JAVA環境下 ReentrantLock 和synchronized 都是 可重入鎖

下面是使用實例

public class Test implements Runnable{    public synchronized void get(){        System.out.println(Thread.currentThread().getId());        set();    }    public synchronized void set(){        System.out.println(Thread.currentThread().getId());    }    @Override    public void run() {       get();    }    public static void main(String[] args) {        Test ss=new Test();        new Thread(ss).start();        new Thread(ss).start();        new Thread(ss).start();    }}

public class Test implements Runnable {    ReentrantLock lock = new ReentrantLock();    public void get() {        lock.lock();        System.out.println(Thread.currentThread().getId());        set();        lock.unlock();    }    public void set() {        lock.lock();        System.out.println(Thread.currentThread().getId());        lock.unlock();    }    @Override    public void run() {        get();    }    public static void main(String[] args) {        Test ss = new Test();        new Thread(ss).start();        new Thread(ss).start();        new Thread(ss).start();    }}

 
兩個例子最后的結果都是正確的,即 同一個線程id被連續輸出兩次。結果如下:Threadid: 8Threadid: 8Threadid: 10Threadid: 10Threadid: 9Threadid: 9可重入鎖最大的作用是避免死鎖我們以自旋鎖作為例子,
public class SpinLock {private AtomicReference<Thread> owner =new AtomicReference<>();	public void lock(){		Thread current = Thread.currentThread();		while(!owner.compareAndSet(null, current)){		}	}	public void unlock (){		Thread current = Thread.currentThread();		owner.compareAndSet(current, null);	}}對于自旋鎖來說,1、若有同一線程兩調用lock() ,會導致第二次調用lock位置進行自旋,產生了死鎖說明這個鎖并不是可重入的。(在lock函數內,應驗證線程是否為已經獲得鎖的線程)2、若1問題已經解決,當unlock()第一次調用時,就已經將鎖釋放了。實際上不應釋放鎖。(采用計數次進行統計)修改之后,如下:
public class SpinLock1 {	private AtomicReference<Thread> owner =new AtomicReference<>();	private int count =0;	public void lock(){		Thread current = Thread.currentThread();		if(current==owner.get()) {		count++;		return ;	}	while(!owner.compareAndSet(null, current)){	}}public void unlock (){	Thread current = Thread.currentThread();	if(current==owner.get()){		if(count!=0){		count--;		}else{			owner.compareAndSet(current, null);		}	}}

該自旋鎖即為可重入鎖。


上一篇:Java解決八皇后問題

下一篇:Java--File類

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
xx视频.9999.com| 久久精品视频免费播放| 国产亚洲精品久久久久久| 日韩欧美在线看| 欧美激情亚洲另类| 亚洲免费人成在线视频观看| 777国产偷窥盗摄精品视频| 久久久人成影片一区二区三区观看| 国产精品xxxxx| 亚洲国产精品热久久| 成人激情视频免费在线| 国产欧美日韩专区发布| 亚洲天堂av在线免费| 国产精品久久久久久久久久久久| 国产精品久久久久久网站| 51ⅴ精品国产91久久久久久| 91精品综合久久久久久五月天| 国产精品福利网| 久久久国产精品一区| 国产亚洲aⅴaaaaaa毛片| 久久成年人视频| 欧美日本高清视频| 亚洲成年网站在线观看| 欧美日韩一区二区三区在线免费观看| 欧美麻豆久久久久久中文| 精品精品国产国产自在线| 国产亚洲一区二区在线| 日韩av电影免费观看高清| 久久精品国产一区| 久久久久久久999精品视频| 日本道色综合久久影院| 国产欧美日韩高清| 96国产粉嫩美女| www国产91| 久久福利视频导航| 成人黄色在线免费| 日韩精品日韩在线观看| 国产精品第1页| 欧美贵妇videos办公室| 性欧美办公室18xxxxhd| 国产免费一区二区三区在线能观看| 日韩在线观看你懂的| 欧美日韩午夜剧场| 成人情趣片在线观看免费| 日韩精品在线免费观看| 亚洲精品午夜精品| 亚洲男人天堂2024| 国产激情999| 亚洲午夜精品久久久久久久久久久久| 最好看的2019的中文字幕视频| 最近2019中文字幕mv免费看| 久久五月天色综合| 韩国国内大量揄拍精品视频| 欧美日韩亚洲视频| xxxxx91麻豆| 5252色成人免费视频| 欧美午夜精品久久久久久人妖| 国产精品在线看| 久久99精品久久久久久琪琪| 秋霞av国产精品一区| 日韩在线观看你懂的| 国产精品久久久av久久久| 亚洲91精品在线观看| 国产精品久久久久久久久久久久| 精品综合久久久久久97| 亚洲国产精品va在线观看黑人| 午夜精品一区二区三区在线播放| 亚洲一区二区日本| 孩xxxx性bbbb欧美| 午夜精品久久久久久久久久久久久| 黑人精品xxx一区一二区| 欧美大片第1页| 日韩精品免费电影| 国产精品久久久久久久久久99| 欧美乱妇40p| 欧美日韩国产成人高清视频| 欧美巨大黑人极品精男| 欧美精品九九久久| 亚洲欧美日韩一区二区在线| 国产精品亚发布| 亚洲伊人成综合成人网| 欧美色视频日本高清在线观看| 国产一区二区视频在线观看| 欧美性猛交xxxxx免费看| 欧美一级黄色网| 日韩av电影在线播放| 日本欧美精品在线| 亚洲精品一区二区在线| 国产亚洲激情视频在线| 欧洲精品毛片网站| 奇米成人av国产一区二区三区| 久久伊人精品视频| 爽爽爽爽爽爽爽成人免费观看| 久久综合久久八八| 2019中文字幕在线| 久久久久久伊人| 91久久在线播放| 中文字幕日韩在线观看| 成人免费大片黄在线播放| 亚洲精品永久免费| 精品高清一区二区三区| 亚洲黄一区二区| 亚洲女人天堂色在线7777| 欧美综合在线第二页| 午夜精品久久久久久久久久久久久| 国产精品自拍偷拍视频| 国产大片精品免费永久看nba| 亚洲美女av在线| 久久乐国产精品| 亚洲成成品网站| 日韩欧美在线免费| 国产精品国模在线| 欧美亚洲午夜视频在线观看| 国产日韩欧美中文在线播放| 亚洲一级片在线看| 国产精品一区二区久久国产| 中文字幕欧美日韩在线| 国产成人亚洲综合91精品| 91在线观看欧美日韩| 久久久精品免费| 国产精品久久久久高潮| 欧美在线免费看| 亚洲香蕉av在线一区二区三区| 久久精品国产电影| 日韩欧美在线免费| 亚洲成av人乱码色午夜| 成人淫片在线看| 成人精品视频99在线观看免费| 亚洲图片在线综合| 97在线视频免费| 久久久久久久久久久网站| 永久免费精品影视网站| 91免费精品国偷自产在线| 欧美日韩国产999| 中文字幕日韩在线观看| 97免费视频在线| 午夜精品在线观看| 欧美激情一区二区三区在线视频观看| 久久精品国产亚洲一区二区| 久久久av网站| 2023亚洲男人天堂| 国产91精品高潮白浆喷水| 欧美丰满少妇xxxxx做受| 免费成人高清视频| 欧美性色xo影院| 中文字幕在线观看亚洲| 亚洲无限av看| 国产精品久久久久久网站| 日韩免费在线看| 精品视频—区二区三区免费| 国产精品电影网站| 日韩中文字幕网址| 国产精品亚洲美女av网站| 欧美激情精品久久久久久蜜臀| 欧美日韩999| 性欧美办公室18xxxxhd| 国产欧美一区二区白浆黑人| 亚洲精选在线观看| 欧美日韩成人在线视频| 高清一区二区三区四区五区| 国产精品免费一区豆花| 4438全国亚洲精品在线观看视频| 亚洲视频在线视频| 国产成人精品在线播放|