Java 線程第三版 第五章 極簡同步技巧 讀書筆記

來源:互聯網
上載者:User

標籤:ntc   atomic   type   end   資料   method   電腦   線程並發   public   



一、能避免同步嗎?取得鎖會由於下面原因導致成本非常高:
    取得由競爭的鎖須要在虛擬機器的層面上執行很多其它的程式碼。
    要取得有競爭鎖的線程總是必須等到鎖被釋放後。


1. 寄存器的效應電腦有一定數量的主寄存器用來儲存與程式有關的資料。


從邏輯上的觀點來看,每一個Thread都有自己的一組寄存器。當作業系統將某個Thread分配給CPU時,它會把該Thread特有的資訊載入到CPU的寄存器中。

在分配不同的Thread給CPU之前,它會將寄存器的資訊存下來。

所以Thread間絕不會共用儲存在寄存器的資料。


當虛擬機器進入synchronized方法或者塊時。它必須又一次載入本來已經緩衝到自有寄存器上的資料。在虛擬機器離開synchroized方法或者塊之前,它必須把自有寄存器存入主寄存器中。




2. 重排語句的效應在單獨線程中。程式總是依照代碼一行行的啟動並執行。可是假設是多個線程並發,Java並不保證每一個線程run方法的運行順序,也就是可能當中一個線程運行到一半就會被臨時停止。運行其它線程,之後再切換回來。


多個線程間調度啟動並執行無序性就是重排語句的效應。




3. 雙重檢查的Locking


二、Atomic變數1. Atomic Class的概述    AtomicInteger, AtomicLong, AtomicBoolean, AtomicRefrences。Atomic的功能實現時通過使用use-level的Java程式無法訪問的固有方法來完畢的。
atomic package支援更複雜的變數類型嗎?


    一些不支援。比如字元或者浮點。
    AtomicStampedReference可以讓mark或stamp跟在不論什麼對象的引用上。
    AtomicMarkableReference提供一個包括對象引用結合boolean的資料結構。




2. 使用Atomic Class
import javax.swing.*;import java.awt.event.*;import java.util.concurrent.*;import java.util.concurrent.atomic.*;import javathreads.examples.ch05.*;public class ScoreLabel extends JLabel implements CharacterListener {    private AtomicInteger score = new AtomicInteger(0);    private AtomicInteger char2type = new AtomicInteger(-1);    private AtomicReference<CharacterSource> generator = null;    private AtomicReference<CharacterSource> typist = null;    public ScoreLabel (CharacterSource generator, CharacterSource typist) {        this.generator = new AtomicReference(generator);        this.typist = new AtomicReference(typist);        if (generator != null)             generator.addCharacterListener(this);        if (typist != null)             typist.addCharacterListener(this);           }    public ScoreLabel () {        this(null, null);    }    public void resetGenerator(CharacterSource newGenerator) {        CharacterSource oldGenerator;        if (newGenerator != null)            newGenerator.addCharacterListener(this);        oldGenerator = generator.getAndSet(newGenerator);        if (oldGenerator != null)            oldGenerator.removeCharacterListener(this);    }    public void resetTypist(CharacterSource newTypist) {        CharacterSource oldTypist;        if (newTypist != null)            newTypist.addCharacterListener(this);        oldTypist = typist.getAndSet(newTypist);        if (oldTypist != null)            oldTypist.removeCharacterListener(this);    }    public void resetScore() {        score.set(0);        char2type.set(-1);        setScore();    }    private void setScore() {        // This method will be explained later in chapter 7        SwingUtilities.invokeLater(new Runnable() {            public void run() {                setText(Integer.toString(score.get()));            }        });    }    public void newCharacter(CharacterEvent ce) {        int oldChar2type;         // Previous character not typed correctly - 1 point penalty        if (ce.source == generator.get()) {            oldChar2type = char2type.getAndSet(ce.character);            if (oldChar2type != -1) {                score.decrementAndGet();                setScore();            }        }        // If character is extraneous - 1 point penalty        // If character does not match - 1 point penalty        else if (ce.source == typist.get()) {            while (true) {                oldChar2type = char2type.get();                if (oldChar2type != ce.character) {                    score.decrementAndGet();                    break;                } else if (char2type.compareAndSet(oldChar2type, -1)) {                    score.incrementAndGet();                    break;                }            }            setScore();        }    } }




變數替換
score與char2type變數已經改成atomic變數。
以上resetScroe方法中對兩個變數進行改動。儘管使用atomic能保證每一個變數的原子性,可是假設多個線程同一時候運行resetScore方法依舊會出現競態條件。
有可能一個線程運行resetScore的第一行代碼score.set(0);還未運行第二行,而另外一個線程可能已經運行newCharacter方法擷取char2type的值,可是之前的線程運行resetScore方法還未對char2type進行改動。由於resetScore整個方法並非原子的。


變更演算法
resetGenerator與resetTypist兩個方法,以resetGenerator方法為例,將generator變數變成AtomicRerence相同引發上面描寫敘述的問題。




通知與Atomic變數

import java.awt.*;import javax.swing.*;import java.util.concurrent.*;import java.util.concurrent.atomic.*;import javathreads.examples.ch05.*;public class AnimatedCharacterDisplayCanvas extends CharacterDisplayCanvas implements CharacterListener, Runnable {    private AtomicBoolean done = new AtomicBoolean(true);    private AtomicInteger curX = new AtomicInteger(0);    private AtomicInteger tempChar = new AtomicInteger(0);    private Thread timer = null;    public AnimatedCharacterDisplayCanvas() {        startAnimationThread();    }    public AnimatedCharacterDisplayCanvas(CharacterSource cs) {        super(cs);        startAnimationThread();    }    private void startAnimationThread() {        if (timer == null) {            timer = new Thread(this);            timer.start();        }    }    public void newCharacter(CharacterEvent ce) {        curX.set(0);        tempChar.set(ce.character);        repaint();    }    protected void paintComponent(Graphics gc) {        char[] localTmpChar = new char[1];        localTmpChar[0] = (char) tempChar.get();        int localCurX = curX.get();        Dimension d = getSize();        int charWidth = fm.charWidth(localTmpChar[0]);        gc.clearRect(0, 0, d.width, d.height);        if (localTmpChar[0] == 0)

Java 線程第三版 第五章 極簡同步技巧 讀書筆記

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.