亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java語(yǔ)言中cas指令的無(wú)鎖編程實(shí)現(xiàn)實(shí)例

 更新時(shí)間:2017年09月14日 08:50:05   投稿:mengwei  
這篇文章主要介紹了Java語(yǔ)言中cas指令的無(wú)鎖編程實(shí)現(xiàn)實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。

最開始接觸到相關(guān)的內(nèi)容應(yīng)該是從volatile關(guān)鍵字開始的吧,知道它可以保證變量的可見性,而且利用它可以實(shí)現(xiàn)讀與寫的原子操作。。。但是要實(shí)現(xiàn)一些復(fù)合的操作volatile就無(wú)能為力了。。。最典型的代表是遞增和遞減的操作。。。。

我們知道,在并發(fā)的環(huán)境下,要實(shí)現(xiàn)數(shù)據(jù)的一致性,最簡(jiǎn)單的方式就是加鎖,保證同一時(shí)刻只有一個(gè)線程可以對(duì)數(shù)據(jù)進(jìn)行操作。。。。例如一個(gè)計(jì)數(shù)器,我們可以用如下的方式來(lái)實(shí)現(xiàn):

public class Counter {
  private volatile int a = 0;
  public synchronized int incrAndGet(int number) {
    this.a += number;
    return a;
  } 
  public synchronized int get() {
    return a;
  }
}

我們對(duì)操作都用synchronized關(guān)鍵字進(jìn)行修飾,保證對(duì)屬性a的同步訪問(wèn)。。。這樣子確實(shí)可以保證在并發(fā)環(huán)境下a的一致性,但是由于使用了鎖,鎖的開銷,線程的調(diào)度等等會(huì)使得程序的伸縮性受到了限制,于是就有了很多無(wú)鎖的實(shí)現(xiàn)方式。。。。

其實(shí)這些無(wú)鎖的方法都利用了處理器所提供的一些CAS(compare and switch)指令,這個(gè)CAS到底干了啥事情呢,可以用下面這個(gè)方法來(lái)說(shuō)明CAS所代表的語(yǔ)義:

public synchronized int compareAndSwap(int expect, int newValue) {
    int old = this.a;
    if (old == expect) {
      this.a = newValue;
    }
    return old;
  }

好吧,通過(guò)代碼應(yīng)該對(duì)CAS語(yǔ)義的標(biāo)書很清楚了吧,好像現(xiàn)在大多數(shù)的處理器都實(shí)現(xiàn)了原子的CAS指令了吧。。
好啦,那么接下來(lái)來(lái)看看在java中CAS都用在了什么地方了吧,首先來(lái)看AtomicInteger類型吧,這個(gè)是并發(fā)庫(kù)里面提供的一個(gè)類型:

private volatile int value;

這個(gè)是內(nèi)部定義的一個(gè)屬性吧,用于保存值,由于是volatile類型的,所以可以保證線程之間的可見性以及讀寫的原子性。。。
那么接下來(lái)來(lái)看看幾個(gè)比較常用的方法:

public final int addAndGet(int delta) {
  for (;;) {
    int current = get();
    int next = current + delta;
    if (compareAndSet(current, next))
      return next;
  }
}

這個(gè)方法的作用是在當(dāng)前值的基礎(chǔ)上加上delta,這里可以看到整個(gè)方法中并沒(méi)有加鎖,這代碼其實(shí)就算是java中實(shí)現(xiàn)無(wú)鎖計(jì)數(shù)器的方法,這里compareAndSet方法的定義如下:

public final boolean compareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

由于調(diào)用了unsafe的方法,所以這個(gè)就無(wú)能為力了,其實(shí)應(yīng)該能猜到JVM調(diào)用了處理器本身的CAS指令來(lái)實(shí)現(xiàn)原子的操作。。。

基本上AtomicInteger類型的重要方法都是采用無(wú)鎖的方式實(shí)現(xiàn)的。。因此在并發(fā)環(huán)境下,用這種類型能有更好的性能。。。
上面算是搞定了在java中實(shí)現(xiàn)無(wú)鎖的計(jì)數(shù)器,接下來(lái)來(lái)看看如何實(shí)現(xiàn)無(wú)鎖棧,直接貼代碼了,代碼是從《JAVA并發(fā)編程實(shí)戰(zhàn)》中模仿下來(lái)的:

package concurrenttest;
import java.util.concurrent.atomic.AtomicReference;
public class ConcurrentStack<e> {
  AtomicReference<node<e>> top = new AtomicReference<node<e>>();
  public void push(E item) {
    Node<e> newHead = new Node<e>(item);
    Node<e> oldHead;
    while (true) {
      oldHead = top.get();
      newHead.next = oldHead;
      if (top.compareAndSet(oldHead, newHead)) {
        return;
      }
    }
  }
  public E pop() {
    while (true) {
      Node<e> oldHead = top.get();
      if (oldHead == null) {
        return null;
      }
      Node<e> newHead = oldHead.next;
      if (top.compareAndSet(oldHead, newHead)) {
        return oldHead.item;
      }
    }
  }
  private static class Node<e> {
    public final E item;
    public Node<e> next;
     
    public Node(E item) {
      this.item = item;
    }
  }
}

好啦,上面的代碼就算是實(shí)現(xiàn)了一個(gè)無(wú)鎖的棧,簡(jiǎn)單吧。。。在并發(fā)環(huán)境中,無(wú)鎖的數(shù)據(jù)結(jié)構(gòu)伸縮性能夠比用鎖好得多。。。
在提到無(wú)鎖編程的時(shí)候,就不得不提到無(wú)鎖隊(duì)列,其實(shí)在concurrent庫(kù)中已經(jīng)提供了無(wú)鎖隊(duì)列的實(shí)現(xiàn):ConcurrentLinkedQueue,我們來(lái)看看它的重要的方法實(shí)現(xiàn)吧:

public boolean offer(E e) {
  checkNotNull(e);
  final Node<e> newNode = new Node<e>(e);
  for (Node<e> t = tail, p = t;;) {
    Node<e> q = p.next;
    if (q == null) {
      // p is last node
      if (p.casNext(null, newNode)) {
        // Successful CAS is the linearization point
        // for e to become an element of this queue,
        // and for newNode to become "live".
        if (p != t) // hop two nodes at a time
          casTail(t, newNode); // Failure is OK.
        return true;
      }
      // Lost CAS race to another thread; re-read next
    }
    else if (p == q)
      // We have fallen off list. If tail is unchanged, it
      // will also be off-list, in which case we need to
      // jump to head, from which all live nodes are always
      // reachable. Else the new tail is a better bet.
      p = (t != (t = tail)) ? t : head;
    else
      // Check for tail updates after two hops.
      p = (p != t && t != (t = tail)) ? t : q;
  }
}

這個(gè)方法用于在隊(duì)列的尾部添加元素,這里可以看到?jīng)]有加鎖,對(duì)于具體的無(wú)鎖算法,采用的是Michael-Scott提出的非阻塞鏈表鏈接算法。。。具體是怎么樣子的,可以到《JAVA并發(fā)編程實(shí)戰(zhàn)》中去看吧,有比較詳細(xì)的介紹。

另外對(duì)于其他方法,其實(shí)都是采用無(wú)鎖的方式實(shí)現(xiàn)的。

最后,在實(shí)際的編程中,在并發(fā)環(huán)境中最好還是采用這些無(wú)鎖的實(shí)現(xiàn),畢竟它的伸縮性更好。

總結(jié)

以上是本文關(guān)于Java語(yǔ)言中cas指令的無(wú)鎖編程實(shí)現(xiàn)實(shí)例的全部介紹,希望對(duì)大家有所幫助!

相關(guān)文章

  • Java中equals和==的區(qū)別詳解

    Java中equals和==的區(qū)別詳解

    這篇文章主要介紹了詳解 Java 中 equals 和 == 的區(qū)別的相關(guān)資料,equals 和 == 都是用來(lái)檢測(cè)兩個(gè)字符串是否相等,返回值也都是布爾型,但是兩者在內(nèi)部比較的處理中卻不盡相同需要的朋友可以參考下
    2021-09-09
  • java簡(jiǎn)單解析xls文件的方法示例【讀取和寫入】

    java簡(jiǎn)單解析xls文件的方法示例【讀取和寫入】

    這篇文章主要介紹了java簡(jiǎn)單解析xls文件的方法,結(jié)合實(shí)例形式分析了java針對(duì)xls文件的讀取和寫入相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2017-06-06
  • 解決復(fù)制springboot項(xiàng)目后,啟動(dòng)日志無(wú)顏色的問(wèn)題

    解決復(fù)制springboot項(xiàng)目后,啟動(dòng)日志無(wú)顏色的問(wèn)題

    這篇文章主要介紹了解決復(fù)制springboot項(xiàng)目后,啟動(dòng)日志無(wú)顏色的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized簡(jiǎn)介

    Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized簡(jiǎn)介

    雖然多線程編程極大地提高了效率,但是也會(huì)帶來(lái)一定的隱患。比如說(shuō)兩個(gè)線程同時(shí)往一個(gè)數(shù)據(jù)庫(kù)表中插入不重復(fù)的數(shù)據(jù),就可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)中插入了相同的數(shù)據(jù)。今天我們就來(lái)一起討論下線程安全問(wèn)題,以及Java中提供了什么機(jī)制來(lái)解決線程安全問(wèn)題。
    2016-05-05
  • SpringIOC refresh()初始化代碼實(shí)例

    SpringIOC refresh()初始化代碼實(shí)例

    這篇文章主要介紹了SpringIOC refresh()初始化代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • java定義通用返回結(jié)果類ResultVO使用示例詳解

    java定義通用返回結(jié)果類ResultVO使用示例詳解

    這篇文章主要為大家介紹了java定義通用返回結(jié)果類ResultVO使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • springboot的jar包如何啟用外部配置文件

    springboot的jar包如何啟用外部配置文件

    本文主要介紹了springboot的jar包如何啟用外部配置文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • logback 自定義Pattern模板教程

    logback 自定義Pattern模板教程

    這篇文章主要介紹了logback 自定義Pattern模板教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • RabbitMQ?Stream插件使用案例代碼

    RabbitMQ?Stream插件使用案例代碼

    這篇文章主要介紹了RabbitMQ?Stream插件使用案例代碼,2.4版為RabbitMQ流插件引入了對(duì)RabbitMQStream插件Java客戶端的初始支持,需要的朋友可以參考下
    2024-04-04
  • Java 二分法檢索算法代碼實(shí)現(xiàn)詳解

    Java 二分法檢索算法代碼實(shí)現(xiàn)詳解

    這篇文章主要介紹了Java 二分法檢索算法代碼實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01

最新評(píng)論