成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java語言中cas指令的無鎖編程實現(xiàn)實例

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

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計、做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、南漳ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的南漳網(wǎng)站制作公司

我們知道,在并發(fā)的環(huán)境下,要實現(xiàn)數(shù)據(jù)的一致性,最簡單的方式就是加鎖,保證同一時刻只有一個線程可以對數(shù)據(jù)進(jìn)行操作。。。。例如一個計數(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;
  }
}

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

其實這些無鎖的方法都利用了處理器所提供的一些CAS(compare and switch)指令,這個CAS到底干了啥事情呢,可以用下面這個方法來說明CAS所代表的語義:

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

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

private volatile int value;

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

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

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

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

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

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

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;
    }
  }
}

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

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

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

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

總結(jié)

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

標(biāo)題名稱:Java語言中cas指令的無鎖編程實現(xiàn)實例
標(biāo)題鏈接:http://jinyejixie.com/article2/psgcic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、網(wǎng)站策劃、GoogleApp設(shè)計、商城網(wǎng)站用戶體驗

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
信阳市| 平顶山市| 朝阳区| 右玉县| 河南省| 万宁市| 盐源县| 保亭| 台北市| 永年县| 和硕县| 岗巴县| 庄浪县| 三穗县| 东山县| 互助| 宜宾县| 七台河市| 黔西| 双桥区| 乌拉特后旗| 诏安县| 积石山| 武义县| 和平县| 泾源县| 晋州市| 泰兴市| 会同县| 凤山市| 文安县| 吴江市| 双辽市| 岳西县| 原平市| 青阳县| 萝北县| 木兰县| 临漳县| 岳普湖县| 嘉义市|