1. 程式人生 > >java 執行緒之同步

java 執行緒之同步

1.執行緒安全

何時出現:當同一資源被多個執行緒同時進行讀寫操作,資料遭到破壞,使得執行結果不準確。
競爭狀態:多個執行緒以一種衝突的方式讀寫公共資源,這種狀態稱為競爭狀態,如果一個類的物件在多執行緒程式中沒有導致競爭狀態,則可稱這個類是執行緒安全的。
解決辦法:同步。避免多個執行緒同時進入程式的某一部分(稱這部分為臨界區),即一次只允許一個執行緒進入這個臨界區。

2.執行緒同步之synchronized

這是一個關鍵字。用於給臨界區上鎖。當第一個執行緒進入臨界區後,給臨界區鎖上,其它執行緒進不來,只能等候第一個執行緒執行完成並釋放鎖,然後下一個獲得鎖,進入臨界區並鎖住臨界區,其它執行緒只能等待它執行完成後並釋放鎖,以此類推。更形象的例子,我們上洗手間,進入,關門,其他人在外等候,等待前一個人處理完成開啟門出來了,第二個人進入,試想如果大家都一起去,結果自己想象,此時執行緒安全問題就出現了。
synchronized之同步,同步方法和同步語句塊。

//同步方法示例
public synchronized void method() {

}

//同步語句塊,不僅可通過this對當前物件加鎖,還可以對任何物件加鎖。
synchronized(expr){  //expr為物件引用,當前物件通常用this。

}

//任何的同步方法都可以轉換為同步語句塊如,如上面的同步方法可改為:
 public void method() {
     synchronized(this){
     }
}

3.synchronized同步分析

程式碼1:不同步

public class SyncTest {
    //方法1
    public
void method1() { System.out.println("進入method1方法"); try { System.out.println("執行method1方法"); Thread.sleep(1000); } catch (Exception e) { } System.out.println("method1方法執行完了"); } //方法2 public void method2() { System.out.println("進入method2方法"
); try { System.out.println("執行method2方法"); Thread.sleep(1000); } catch (Exception e) { } System.out.println("method2方法執行完了"); } public static void main(String[] args) { SyncTest test = new SyncTest(); //執行緒1 new Thread(new Runnable() { @Override public void run() { test.method1(); } }).start(); //執行緒2 new Thread(new Runnable() { @Override public void run() { test.method2(); } }).start(); } } //執行結果,方法1和方法2同時執行 /* 進入method1方法 執行method1方法 進入method2方法 執行method2方法 method2方法執行完了//此處也可能是method1先執行完 method1方法執行完了 */

程式碼2:synchronized同步普通方法

public class SyncTest {
    //方法1,注意synchronized的位置,在返回值前
    public synchronized void  method1() {
        System.out.println("進入method1方法");
        try {
            System.out.println("執行method1方法");
            Thread.sleep(1000);
        } catch (Exception e) {
        }
        System.out.println("method1方法執行完了");
    }
    //方法2
    public synchronized void method2() {
        System.out.println("進入method2方法");
        try {
            System.out.println("執行method2方法");
            Thread.sleep(1000);
        } catch (Exception e) {
        }
        System.out.println("method2方法執行完了");
    }

    public static void main(String[] args) {
        SyncTest test = new SyncTest();
        //執行緒1
        new Thread(new Runnable() {

            @Override
            public void run() {
                test.method1();
            }

        }).start();
        //執行緒2
        new Thread(new Runnable() {

            @Override
            public void run() {
                test.method2();
            }

        }).start();
    }
}
//執行結果,方法1執行完成後才會執行方法2,產生了同步效果
/*
進入method1方法
執行method1方法
method1方法執行完了
進入method2方法
執行method2方法
method2方法執行完了
*/

程式碼3:synchronized同步程式碼塊

public class SyncTest {

    //方法1
    public void  method1() {
        System.out.println("進入method1方法");
        try {
            synchronized(this) {
                Thread.sleep(1000);
                System.out.println("執行method1方法");
            }
        } catch (Exception e) {
        }
        System.out.println("method1方法執行完了");
    }
    //方法2
    public void method2() {
        System.out.println("進入method2方法");
        try {
            synchronized(this) {
                Thread.sleep(1000);
                System.out.println("執行method2方法");
            }
        } catch (Exception e) {
        }
        System.out.println("method2方法執行完了");
    }

    public static void main(String[] args) {
        SyncTest test = new SyncTest();
        //執行緒1
        new Thread(new Runnable() {

            @Override
            public void run() {
                test.method1();
            }

        }).start();
        //執行緒2
        new Thread(new Runnable() {

            @Override
            public void run() {
                test.method2();
            }

        }).start();
    }
}
//執行結果,方法1中同步塊中的執行了才會執行方法2中的同步塊。

程式碼4:synchronized同步靜態方法

public class SyncTest {

    //靜態方法1
    public synchronized static void  method1() {
        System.out.println("進入method1方法");
        try {
            System.out.println("執行method1方法");
            Thread.sleep(1000);
        } catch (Exception e) {
        }
        System.out.println("method1方法執行完了");
    }
    //靜態方法2
    public static synchronized void method2() {
        System.out.println("進入method2方法");
        try {
            System.out.println("執行method2方法");
            Thread.sleep(1000);
        } catch (Exception e) {
        }
        System.out.println("method2方法執行完了");
    }

    public static void main(String[] args) {
        SyncTest test1 = new SyncTest();//物件1
        SyncTest test2 = new SyncTest();//物件2
        //執行緒1
        new Thread(new Runnable() {

            @Override
            public void run() {
                test1.method1();
            }

        }).start();
        //執行緒2
        new Thread(new Runnable() {

            @Override
            public void run() {
                test2.method2();
            }

        }).start();
    }
}
//執行結果,雖然物件test1和物件test2是不同的物件,但是它們同屬一個類。方法1執行完成後才會執行方法2.
/*
進入method1方法
執行method1方法
method1方法執行完了
進入method2方法
執行method2方法
method2方法執行完了
*/

4.Lock類

4.1 Lock與synchronized的區別:

  • a: Lock是一個類,在java 1.5版本中提供;synchronized是一個關鍵字。因此Lock的功能比synchronized強大。
  • b: 線上程執行完以後,synchronized會自動釋放執行緒所持有的監視器鎖;而Lock則需要手動去釋放鎖,因此在使用Lock時執行緒塊常放在try-finally塊中,並在finally中呼叫unlock方法釋放鎖。
  • c: synchronized強制鎖的獲取與釋放都必須在同一個塊結構中;而Lock則允許在不同的結構中獲取和釋放鎖,也可以以任何順序獲取和釋放多個鎖。關於此條的理解閱讀後面相關例子。

4.2 Lock介面常用方法

  • void lock() 獲取鎖

    Lock lock = ....;
    lock.lock();//獲取鎖
  • void unlock() 釋放鎖 ,在finally塊中呼叫,以確保鎖會被釋放。

    Lock lock = ...;
    lock.lock();
    try{
        //處理任務
    } finally {
        lock.unlock();
    }
  • boolean tryLock() 如果當前鎖為空閒狀態,則獲取鎖並返回true,否則返回false。

    Lock lock = ...;
    if(lock.tryLock()){
        try{
            //處理任務
        } finally {
            lock.unlock();
        }
    } else {
        //如果拿不到鎖,則另行處理其他業務
    }
  • boolean tryLock(long time, TimeUnit unit)如果在指定時間time內沒有獲取獲取,則返回false,TimeUnit是一個列舉,用來表示時間粒度。如時,分,秒,毫秒…。
    Lock lock = ...;
    if(lock.tryLock(100L,TimeUnit.MILLISECONDS)){//表示在100毫秒後超時。
        try{
            //處理任務
        } finally {
            lock.unlock();
        }
    } else {
        //如果拿不到鎖,則另行處理其他業務
    }
  • void lockInterruptibly()
  • Condition newCondition()

相關推薦

java 執行同步

1.執行緒安全 何時出現:當同一資源被多個執行緒同時進行讀寫操作,資料遭到破壞,使得執行結果不準確。 競爭狀態:多個執行緒以一種衝突的方式讀寫公共資源,這種狀態稱為競爭狀態,如果一個類的物件在多執行緒程式中沒有導致競爭狀態,則可稱這個類是執行緒安全的。 解

Java執行Synchronized同步————Java學習路(17)

前言——不進則退啊,部落格幾天沒寫,排名第一次下降了,得勤奮更新,不能偷懶。。 歡迎轉載,轉載請註明來處。 目錄 一.演示同步問題 此前,我們用的多執行緒都是較為簡單的例子,都沒有涉及到多個執行緒共享同一個物件或者資源的情況。倘若多執行緒共享資

java執行同步鎖(Lock)

      從Java5開始,提供了Lock, Lock提供了比synchronized方法和synchronized程式碼塊更廣泛的鎖定操作,Lock可以實現更靈活的結構,並且支援多個相關的Condition物件(物件監視器)。       Lock是控制多個執行緒對共享

java執行同步計數器

同步計數器之--CountDownLatch    使用場景:當用戶上傳檔案,我們可以多開幾個執行緒來上傳檔案,當所有的執行緒上傳完成後,檔案才算上傳完成,在此場景下可以使用CountDownLatch,當每個執行緒上傳完成,呼叫CountDownLatch.countDow

java 執行執行狀態

java執行緒狀態 1. 初始(NEW):新建立了一個執行緒物件,但還沒有呼叫start()方法。 2. 執行(RUNNABLE): Java執行緒中將就緒(ready)和執行中(running)兩種狀態籠統的稱為“執行”。 執行緒物件建立後,其他執行緒(比如main執行緒)呼叫了該物件

Java執行semaphore和Exchanger

Semaphore是Java執行緒的一個計數訊號量。我們可用於多執行緒的併發訪問控制。 就像我們常見的執行緒池,資料庫連線池就可以使用Semaphore進行邏輯的實現。Semaphore中我們就介紹兩個最常用的兩個方法。 acquire() 從Semaphore獲取許可,如果計數不小於0

執行同步鎖 加鎖和執行停止

一.同步程式碼塊(同步鎖) 寫法: synchronized(鎖){ 上鎖的程式碼 } 當執行緒進入同步程式碼塊 會把鎖拿走 執行程式碼塊中的程式碼 程式碼執行完畢後 會把鎖還回去 如果執行緒遇到同步程式碼塊 發現沒有鎖 將進入等待(有鎖才可進) 鎖的注意:保證所有執行緒使用的是同一個鎖

Java執行非同步回撥(Callback)

●介紹      有時候執行一個任務需要很長時間,單執行緒下執行緒會處於阻塞狀態。這個時候我們會考慮一種非阻塞的處理模式。非阻塞任務在任何程式語言裡都必不可少,Java也不例外。多執行緒就是一個很好的解決辦法。     

Java執行同步(詭異的IllegalMonitorStateException )

  前兩天去面試,被問到了一個執行緒同步的問題,兩個執行緒依次輸出1……100,一個執行緒只輸出奇數,一個只輸出偶數。之前工作中沒寫過執行緒同步的程式碼,只知道使用object的wait()和notify()方法可以實現執行緒同步,之前也看過執行緒池實現的程式碼,用的也是wait()和not

java執行Latch設計模式見解

CountDownLatch :(個人理解)使用閥門值,直到閥門值為0之前,一直阻塞執行緒。實則使用物件鎖,不釋放物件鎖,一直佔用資源,(這裡是一個缺點)。閥門值為0時,呼叫釋放物件鎖的方法,釋放資源。應用的場景,我覺得是需要一些執行緒先完成的前提下,再使用其他執行緒。也就是我就是要一些重要的執行緒

Java執行訊號量

 計數訊號量用來控制同時訪問某個特定資源的運算元量,或者同時執行某個指定操作的數量。計數訊號量還可以用來實現某種資源池,或者對容器施加邊界。  Semaphore中管理者一組虛擬的許可,許可的數量可通過建構函式來指定。在互相操作時可以首先獲得許可(只要還有剩餘的許可),並在使用以後釋放許可。

Java執行閉鎖

 閉鎖是一種同步工具類,可以延遲執行緒的進度直到其到達終止狀態。閉鎖的作用相當於一扇門:在閉鎖到達結束狀態之前,這扇門一直是關閉的,並且沒有任何執行緒能通過,當到達結束狀態時,這扇門會開啟並允許所有的執行緒通過。當閉鎖到達結束狀態後,將不會再改變狀態,因此這扇門將永遠保持開啟狀態。閉鎖可以用

Java執行同步

程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。 執行緒是程序中的一個執行單元,負責當前程序中程式的執行,一個程序中至少有一個執行緒。一個程序中是可以有多個執行緒的,這個應用程式也可以稱之為多執

java執行Executor框架與執行

執行緒雖然在web開發中用的不算特別多,但在特定的情況下還是能發揮重要重要作用的,因此即使用的少還是掌握下比較好;下面先回顧下比較執行緒的常規實現方法 1 繼承Thread類 2 實現runnable介面(使用較多) java5之後有了新的執行緒實現方式,java5可以使用

Java執行銀行存取款

銀行的存取款可以分為存款和取款: 當去存款的時候會先顯示賬戶資訊,然後將存進去的錢和賬戶原有的錢數相加,返回存款之後賬戶資訊; 當去取款的時候會先顯示賬戶資訊,然後將取錢數和賬戶裡面的錢相對比,如果取

Java執行執行池的使用

 在Java中進行非同步操作時,執行緒必不可少,但如果頻繁的建立、銷燬一個執行緒,這是很耗效能的,所以執行緒池就應運而生了,Java中主要有newFixedThreadPool、newCachedThreadPool、newSingleThreadExecuter及newSchedule

Java執行執行

 Executor框架可以將任務的提交與任務的執行策略解耦開來。就像許多對複雜過程的解耦操作那樣,這種論斷多少有些言過其實了。雖然Executor框架為定製和修改執行策略提供了相當大的靈活性,但並非所有的任務都能適用所有的執行策略。有些型別的任務需要明確的指定執行策略。

java執行wait(),notify(),notifyAll(),synchronized(obj){},join()

wait(),notify(),notifyAll(),synchronized wait()和notify()是java.lang.Object的物件方法,synchronized是java關鍵字;wait()和notify()必須配合synchronized

JAVA#執行'同步程式碼塊 札記

public static void main(String[] args) { Shixian s1=new Shixian(); Thread t1=new Thread(s1); t1.setName("宋小艾"); t1.st

Java執行fork/join框架

fork/join框架是用多執行緒的方式實現分治法來解決問題。fork指的是將問題不斷地縮小規模,join是指根據子問題的計算結果,得出更高層次的結果。 fork/join框架的使用有一定的約束條件: 1. 除了fork()  和  join()方法外,執行緒不得使用