1. 程式人生 > >使用synchronized實現同步方法

使用synchronized實現同步方法

1、簡介

使用synchronized關鍵字來控制一個方法的併發訪問。如果一個物件已用synchronized關鍵字宣告,那麼只允許一個執行執行緒訪問它。如果其他某個執行緒試圖訪問這個物件的其他方法,它將被阻塞直到第一個執行緒執行完正在執行的方法。

每一個用synchronized關鍵字申明的方法都是臨界區,在java中,同一物件的臨界區,在同一時間只有一個允許被訪問。

2、程式碼例項

package com.xxx.util;

/**
 * Created with IntelliJ IDEA.
 * Date: 15-4-21
 * Time: 下午3:45
 * To change this template use File | Settings | File Templates.
 */
public class Account {

    private double balance;

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public synchronized void addAmount(double amount){
        double temp = balance;
        temp +=amount;
        try {
            Thread.sleep(10);//模擬其它處理所需要的時間,比如重新整理資料庫等
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        balance = temp;
    }

    public synchronized void subtractAmount(double amount){
        double temp = balance;
        temp -=amount;
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        balance = temp;
    }

}

package com.xxx.util;

/**
 * Created with IntelliJ IDEA.
 * Date: 15-4-21
 * Time: 下午3:51
 * To change this template use File | Settings | File Templates.
 */
public class Bank implements Runnable {

    private Account account;

    public Bank(Account account){
        this.account = account;
    }

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            account.subtractAmount(1000);
        }
    }
}

package com.xxx.util;

/**
 * Created with IntelliJ IDEA.
 * Date: 15-4-21
 * Time: 下午3:54
 * To change this template use File | Settings | File Templates.
 */
public class Company implements Runnable {

    private Account account;

    public Company(Account account){
        this.account = account;
    }

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            account.addAmount(1000);
        }
    }
}
package com.xxx.util;

/**
 * Created with IntelliJ IDEA.
 * Date: 15-4-21
 * Time: 下午3:56
 * To change this template use File | Settings | File Templates.
 */
public class SynchronizedThreadMain {

    public static void main(String[] args){
        Account account = new Account();
        account.setBalance(1000);
        System.out.printf("Acount: initial balance:%.2f\n",account.getBalance());
        Company company = new Company(account);
        Thread companyThread = new Thread(company);
        Bank bank = new Bank(account);
        Thread bankThread = new Thread(bank);
        companyThread.start();
        bankThread.start();
        try {
            companyThread.join();//等待執行緒companyThread執行結束
            bankThread.join();
            System.out.printf("Acount: final balance:%.2f\n",account.getBalance());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
3、執行結果

4、總結

(1)、synchronized關鍵字的作用域有二種: 
1)是某個物件例項內,synchronized aMethod(){}可以防止多個執行緒同時訪問這個物件的synchronized方法(如果一個物件有多個synchronized方法,只要一個執行緒訪問了其中的一個synchronized方法,其它執行緒不能同時訪問這個物件中任何一個synchronized方法)。這時,不同的物件例項的synchronized方法是不相干擾的。也就是說,其它執行緒照樣可以同時訪問相同類的另一個物件例項中的synchronized方法; 
2)是某個類的範圍,synchronized static aStaticMethod{}防止多個執行緒同時訪問這個類中的synchronized static 方法。它可以對類的所有物件例項起作用。

(2)、除了方法前用synchronized關鍵字,synchronized關鍵字還可以用於方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。用法是: synchronized(this){/*區塊*/},它的作用域是當前物件;

(3)、synchronized關鍵字是不能繼承的,也就是說,基類的方法synchronized f(){} 在繼承類中並不自動是synchronized f(){},而是變成了f(){}。繼承類需要你顯式的指定它的某個方法為synchronized方法;

Java語言的關鍵字,當它用來修飾一個方法或者一個程式碼塊的時候,能夠保證在同一時刻最多隻有一個執行緒執行該段程式碼。

     一、當兩個併發執行緒訪問同一個物件object中的這個synchronized(this)同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程式碼塊以後才能執行該程式碼塊。

     二、然而,當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,另一個執行緒仍然可以訪問該object中的非synchronized(this)同步程式碼塊。

     三、尤其關鍵的是,當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,其他執行緒對object中所有其它synchronized(this)同步程式碼塊的訪問將被阻塞。

     四、當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,它就獲得了這個object的物件鎖。結果,其它執行緒對該object物件所有同步程式碼部分的訪問都被暫時阻塞。

     五、以上規則對其它物件鎖同樣適用.




相關推薦

使用synchronized實現同步方法

1、簡介 使用synchronized關鍵字來控制一個方法的併發訪問。如果一個物件已用synchronized關鍵字宣告,那麼只允許一個執行執行緒訪問它。如果其他某個執行緒試圖訪問這個物件的其他方法,它將被阻塞直到第一個執行緒執行完正在執行的方法。 每一個用synchron

GCD實現同步方法

任務 初始 out nal 方法 semaphore 資源 jsb v操作 在iOS多線程中我們知道NSOperationQueue操作隊列可以直接使用addDependency函數設置操作之間的依賴關系實現線程同步,還可以使用setMaxConcurrentOperat

同步(同步程式碼塊synchronized(this) 同步方法 、全域性鎖、同步處理方法對比)

為什麼會出現同步處理? 如果要寫一個多個執行緒賣票的程式碼,按照原本思路程式碼如下: class MythreadB implements Runnable { private Integer tickets=10; public void run() {

java 多執行緒synchronized同步方法,同步程式碼塊

執行緒安全問題 同步和非同步 我們知道多個執行緒共享堆記憶體,當兩個或者多個執行緒呼叫同一個物件的方法操作物件成員時,因為cpu輪流執行執行緒,執行緒A剛開始操作物件方法,修改了資料,輪到執行緒B執行,執行緒B也操作物件方法,修改資料,可能又輪到執行緒A操作物件方法,接著上次執行緒A的剩餘部

Java中synchronized同步方法

在多執行緒中,有一個經典問題:存票售票問題 如果只用兩個Thread子類則容易陷入死迴圈。 有一個很好的解決辦法就是synchronized。 方法一:在thread子類的run中直接通過synchronized來申請物件的鎖旗標,即用synchronized把存售票程式碼框起來。 方法二:在票類中直

執行緒安全-鎖機制 synchronized用法同步方法

一個簡單的例子,10個人搶8張票,結果肯定是有2個人搶不到票的 public class Ticket { private static CountDownLatch ctl =new CountDownLatch(1); private Reentra

[CareerCup] 16.6 Synchronized Method 同步方法

16.6 You are given a class with synchronized method A and a normal method B. If you have two threads in one instance of a program, can they both execute

執行緒中的同步程式碼塊synchronized同步方法同步鎖Lock

在學習執行緒的時候,因為執行緒的排程具有不確定性,所以銀行取錢問題、多個視窗售賣火車票問題都是反應多執行緒的優越性以及不確定性。當程式中有多個併發執行緒在進入一個程式碼塊中並且修改其中引數時,就很有可能引發執行緒安全問題從而造成異常。 同步程式碼塊 所以,j

synchronized實現同步的三種用法

1:對於普通同步方法,鎖的是當前例項的物件。 意思是 class A { synchronized test(){ system.out.print("lock object"); } } A a = new A();A a1 = new A();a.test(

NodeJS實現同步方法

inter ews ttr 功能 同步 異步 splay led ng- NodeJS被打上了單線程、非阻塞、事件驅動…..等標簽。 在單線程的情況下,是無法開啟子線程的。經過了很久的研究,發現並沒有thread函數!!!但是有時候,我們確實需要“多線程”處理事務。no

synchronized同步方法

setvalue 父類 關鍵字 end val 產生 add int getname 一、方法內的變量是線程安全的   “非線程安全”問題存在於“實例變量”中,如果是方法內部的私有變量,則不存在“非線程安全”問題,所得結果也就是“線程安全”的了 二、實例變量非線程安全   

深入理解使用synchronized同步方法和同步代碼塊的區別

sys http ted 兩個 方法 ext tar extends idt 一.代碼塊和方法之間的區別 首先需要知道代碼塊和方法有什麽區別: 構造器和方法塊,構造器可以重載也就是說明在創建對象時可以按照不同的構造器來創建,那麽構造器是屬於對象,而代碼塊呢他是給所有的對象初

二十二 synchronized同步方法

需要 訪問 調用 鎖重入 方法 syn 永遠 sync ont 一 Synchronized鎖:   1 synchronized取得的鎖都是對象鎖,而不是把一段代碼或方法加鎖。   synchronized是給該方法的實例對象加鎖。如果多個線程訪問的是同一個對象

Java多執行緒學習筆記(二) synchronized同步方法-防止髒讀

1. 髒讀 在給一個物件賦值的時候進行了同步, 但是在取值的時候可能出現意外,此值已經被其他執行緒修改了,這種情況就是髒讀 1.1 PublicVar類 public class PublicVar { public String userName = "wang don

Java多執行緒學習筆記(一) synchronized同步方法

synchronized同步方法 1.提出問題-例項變數非執行緒安全 1.1 何為非執行緒安全? 1.2 舉例 1.2.1 有私有變數的類HasPrivateNum (供多執行緒們去呼叫) 1.2.2 執行緒A

深入理解使用synchronized同步方法同步程式碼塊的區別

一.程式碼塊和方法之間的區別 首先需要知道程式碼塊和方法有什麼區別: 構造器和方法塊,構造器可以過載也就是說明在建立物件時可以按照不同的構造器來建立,那麼構造器是屬於物件,而程式碼塊呢他是給所有的物件初始化的。底下看一個列子: public class Constructor_Methodbloc

Java多執行緒程式設計筆記2:synchronized同步方法

非執行緒安全會在多個執行緒對同一個物件中的例項變數進行併發訪問時發生,產生的結果就是髒讀,也就是取到的資料是被更改過的。執行緒安全就是獲得的例項變數的值是經過同步處理的。 方法內的變數是執行緒安全的 方法內的變數是執行緒安全的。非執行緒安全的問題存在於例項變數中,如果是方法內部的私有變數,不存在非執行緒安

java,Synchronized同步方法例項(一)

是執行緒獲取物件的鎖,且該執行緒執行物件所屬類中的同步方法! 當然執行緒也是物件,也有鎖,鎖只是物件的一個標誌位。 哪個執行緒獲得了SynClass的物件鎖,則哪個執行緒進入同步方法中執行 publi

java synchronized(靜態同步方法、非靜態同步方法同步塊)

同步方法   同步方法所擁有的鎖就是該方法所屬的類的物件鎖,換句話說,也就是this物件,而且鎖的作用域也是整個方法,這可能導致其鎖的作用域可能太大,也有可能引起死鎖,同時因為可能包含了不需要進行同步的程式碼塊在內,也會降低程式的執行效率。 同步方法的鎖   同

Java學習筆記(一) Java多執行緒 synchronized同步方法

1.提出問題-例項變數非執行緒安全 如果多個執行緒同時訪問1個物件的例項變數,則可能出現"非執行緒安全"問題。 1.1 何為非執行緒安全? 我的理解是多個執行緒對一個例項變數操作會出現值被更改,不同步的情況。 1.2 舉例 1.2.1 有私有變數的類HasPr