多線程併發的解決方案 volatile synchronized notify notifyAll wait關鍵字分析

1.ThreadLocal用法

在java中,若是一個變量須要被多個線程訪問,可使用volatile來聲明它爲「易變的」。而假如一個變量要被持有它的某個線程獨享,在java中,它可使用java.lang.ThreadLocal類來實現線程本地存儲的功能。這樣,數據便只在同一個線程內可見和共享,所以,即使不一樣步也能保證線程之間不出現數據爭用。java

ThreadLocal使得各線程可以保持各自獨立的一個對象,經過ThreadLocal.set()來設置對象的值,保存在每一個線程本身都有的一個map對象當中,每一個ThreadLocal對象會有一個線程範圍內惟一hashcode做爲key,ThreadLocal.get()內部經過這個key從map中取值,所以取出來的是各自本身線程中的對象,ThreadLocal實例事實上只是做爲map的key來使用的併發

 

ThreadLocal例子ide

package com.arch.demo;

public class ThreadLocalTest {

    public static void main(String[] args) {
        ThreadLocal<Integer> count = new ThreadLocal<>();

        ConcurrentThread t1 = new ConcurrentThread(count);
        ConcurrentThread t2 = new ConcurrentThread(count);
        ConcurrentThread t3 = new ConcurrentThread(count);
        ConcurrentThread t4 = new ConcurrentThread(count);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }


   static class ConcurrentThread extends Thread {

        ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

        private ConcurrentThread(ThreadLocal<Integer> count) {
            this.threadLocal = count;
        }

        @Override
        public void run() {
            for (int i = 1; i < 10; i++) {
                if (threadLocal.get() != null) {
                    threadLocal.set(threadLocal.get() + 1);
                } else {
                    threadLocal.set(1);
                }
                System.out.println("Thread:" + this.currentThread().getName() + ",Count:" + threadLocal.get());
            }
        }
    }
}

 

2.volatile用法

volatile是輕量級的synchronized, 它在多處理器開發中保證了共享變量的"可見性", 可見性是指一個線程在修改共享變量的值時,其餘的線程能夠讀到這個修改的值oop

 

3.Synchronized與ReentranckLock區別

 

  1. Lock和 synchronized 有一點明顯的區別 —— lock 必須在 finally 塊中釋放 

    2. Lock能夠實現公平鎖或不公平鎖,而Synchronized是不公平的,並且永遠都是不公平的。但 JVM 保證了全部線程最終都會獲得它們所等候的鎖,可是Lock做爲默認設置,把公平設置爲false 性能

     3. Lock性能和伸縮性都比較好(在JDK5.0),可是大多數狀況Synchronized就足夠了,並且更容易理解this

     4.ReentrantLock是一個可重入的互斥鎖,又被稱爲「獨佔鎖」。也就是說ReentrantLock在同一個時間點只能被一個線程獲取spa

 

4. 重要點線程

  1).當兩個併發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程獲得執行。另外一個線程必須等待當前線程執行完這個代碼塊之後才能執行該代碼塊code

public class SynchronizedThread implements Runnable {
    @Override
    public void run() {
        synchronized (this){
            for(int i = 0; i < 5; i++){
                System.out.println(Thread.currentThread().getName() + " synchronized loop" + i);
            }
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new SynchronizedThread();

        new Thread(runnable,"a").start();
        new Thread(runnable,"b").start();
    }
}

 

  2).當一個線程訪問object的一個synchronized(this)同步代碼塊時,另外一個線程仍然能夠訪問該object中的非synchronized(this)同步代碼塊對象

相關文章
相關標籤/搜索