<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 15,  comments - 9,  trackbacks - 0

              在大多數實際運行的多線程應用程序中,二個或多個線程需要共享對同一對象的訪問。如果二個線程訪問同一個對象,并且每個線程抖調用同一個方法,以便修改該對象的狀態,那將出現什么樣的情況呢?
            書中最常見的例子就是銀行取款的例子。假如一個人在銀行里開了10個帳戶,外面設置10個線程,每個帳戶一個線程。每個交易事務負責將一筆隨機數額的資金從該線程服務的帳戶轉移到另一個隨機帳戶。
             在沒有對共享資源的訪問實施同步(synchronized)之前,在同時進行轉賬時,就會出現錯誤。例如下面一代代碼:

     

    public class UnsynchBankTest

       
    public static void main(String[] args)
       
    {  
          Bank b 
    = new Bank(NACCOUNTS, INITIAL_BALANCE);
          
    int i;
          
    for (i = 0; i < NACCOUNTS; i++)
          
    {  
             TransferThread t 
    = new TransferThread(b, i,
                INITIAL_BALANCE);
             t.setPriority(Thread.NORM_PRIORITY 
    + i % 2);
             t.start();
          }

       }


       
    public static final int NACCOUNTS = 10;
       
    public static final int INITIAL_BALANCE = 10000;
    }


    /** *//**
       A bank with a number of bank accounts.
    */

    class Bank

       
    /** *//**
          Constructs the bank.
          
    @param n the number of accounts
          
    @param initialBalance the initial balance
          for each account
       
    */

       
    public Bank(int n, int initialBalance)
       
    {  
          accounts 
    = new int[n];
          
    int i;
          
    for (i = 0; i < accounts.length; i++)
             accounts[i] 
    = initialBalance;
          ntransacts 
    = 0;
       }


       
    /** *//**
          Transfers money from one account to another.
          
    @param from the account to transfer from
          
    @param to the account to transfer to
          
    @param amount the amount to transfer
       
    */

       
    public void transfer(int from, int to, int amount)
          
    throws InterruptedException
       
    {  
          accounts[from] 
    -= amount;
          accounts[to] 
    += amount;
          ntransacts
    ++;
          
    if (ntransacts % NTEST == 0) test();
       }


       
    /** *//**
          Prints a test message to check the integrity
          of this bank object.
       
    */

       
    public void test()
       
    {  
          
    int sum = 0;

          
    for (int i = 0; i < accounts.length; i++)
             sum 
    += accounts[i];

          System.out.println(
    "Transactions:" + ntransacts
             
    + " Sum: " + sum);
       }


       
    /** *//**
          Gets the number of accounts in the bank.
          
    @return the number of accounts
       
    */

       
    public int size()
       
    {  
          
    return accounts.length;
       }


       
    public static final int NTEST = 10000;
       
    private final int[] accounts;
       
    private long ntransacts = 0;
    }


    /** *//**
       A thread that transfers money from an account to other
       accounts in a bank.
    */

    class TransferThread extends Thread
    {  
       
    /** *//**
          Constructs a transfer thread.
          
    @param b the bank between whose account money is transferred
          
    @param from the account to transfer money from
          
    @param max the maximum amount of money in each transfer 
       
    */

       
    public TransferThread(Bank b, int from, int max)
       
    {  
          bank 
    = b;
          fromAccount 
    = from;
          maxAmount 
    = max;
       }


       
    public void run()
       
    {  
          
    try
          
    {  
             
    while (!interrupted())
             
    {  
                
    for (int i = 0; i < REPS; i++)
                
    {
                   
    int toAccount = (int)(bank.size() * Math.random());
                   
    int amount = (int)(maxAmount * Math.random() / REPS);
                   bank.transfer(fromAccount, toAccount, amount);
                   sleep(
    1);
                }

             }

          }

          
    catch(InterruptedException e) {}
       }


       
    private Bank bank;
       
    private int fromAccount;
       
    private int maxAmount;
       

    運行一段時間后會發現,sum(總金額發生了變化)。
    下面這段代碼是對共享資源的訪問實施同步:

    public class SynchBankTest

       
    public static void main(String[] args)
       
    {  
          Bank b 
    = new Bank(NACCOUNTS, INITIAL_BALANCE);
          
    int i;
          
    for (i = 0; i < NACCOUNTS; i++)
          
    {  
             TransferThread t 
    = new TransferThread(b, i,
                INITIAL_BALANCE);
             t.setPriority(Thread.NORM_PRIORITY 
    + i % 2);
             t.start();
          }

       }


       
    public static final int NACCOUNTS = 10;
       
    public static final int INITIAL_BALANCE = 10000;
    }


    /**
       A bank with a number of bank accounts.
    */

    class Bank

       
    /**
          Constructs the bank.
          
    @param n the number of accounts
          
    @param initialBalance the initial balance
          for each account
       
    */

       
    public Bank(int n, int initialBalance)
       
    {  
          accounts 
    = new int[n];
          
    int i;
          
    for (i = 0; i < accounts.length; i++)
             accounts[i] 
    = initialBalance;
          ntransacts 
    = 0;
       }


       
    /**
          Transfers money from one account to another.
          
    @param from the account to transfer from
          
    @param to the account to transfer to
          
    @param amount the amount to transfer
       
    */

       
    public synchronized void transfer(int from, int to, int amount)
          
    throws InterruptedException
       
    {  
          
    while (accounts[from] < amount)
             wait();
          accounts[from] 
    -= amount;
          accounts[to] 
    += amount;
          ntransacts
    ++;
          notifyAll();
          
    if (ntransacts % NTEST == 0) test();
       }


       
    /**
          Prints a test message to check the integrity
          of this bank object.
       
    */

       
    public synchronized void test()
       
    {  
          
    int sum = 0;

          
    for (int i = 0; i < accounts.length; i++)
             sum 
    += accounts[i];

          System.out.println(
    "Transactions:" + ntransacts
             
    + " Sum: " + sum);
       }


       
    /**
          Gets the number of accounts in the bank.
          
    @return the number of accounts
       
    */

       
    public int size()
       
    {  
          
    return accounts.length;
       }


       
    public static final int NTEST = 10000;
       
    private final int[] accounts;
       
    private long ntransacts = 0;
    }


    /**
       A thread that transfers money from an account to other
       accounts in a bank.
    */

    class TransferThread extends Thread
    {  
       
    /**
          Constructs a transfer thread.
          
    @param b the bank between whose account money is transferred
          
    @param from the account to transfer money from
          
    @param max the maximum amount of money in each transfer 
       
    */

       
    public TransferThread(Bank b, int from, int max)
       
    {  
          bank 
    = b;
          fromAccount 
    = from;
          maxAmount 
    = max;
       }


       
    public void run()
       
    {  
          
    try
          
    {  
             
    while (!interrupted())
             
    {  
                
    int toAccount = (int)(bank.size() * Math.random());
                
    int amount = (int)(maxAmount * Math.random());
                bank.transfer(fromAccount, toAccount, amount);
                sleep(
    1);
             }

          }

          
    catch(InterruptedException e) {}
       }


       
    private Bank bank;
       
    private int fromAccount;
       
    private int maxAmount;
    }


    運行后,sum未發生變化。
    簡要說明一下同步機制是如何運行的:
    1.若要調用synchronized方法,隱含參數不應該被鎖定。調用該方法便可鎖定該對象。而從該調用返回則可撤銷對隱含參數對象的鎖定。因此,每次只有一個線程能夠在特定對象上執行synchronized方法。
    2.當一個線程執行對wait方法的調用時,他將釋放對象鎖,而且進入該對象的等待列表。
    3.要從等待列表中刪除一個線程,另外的莫個線程必須調用同一對象上的notifyALL或notify方法。
         調度原則確實是復雜的,不過使用起來是相對簡單的。你只要按照下面的5條原則進行操作即可:
    1.如果二個或多個線程修改一個對象,請將執行修改的方法聲明為synchronized方法。受到對象修改影響的只讀方法也必須實現同步。
    2.如果一個線程必須等待某個對象的狀態出項變更,那么它應該在對象的內部等待,而不是在外邊等待,這可以通過輸入一個synchronized方法,并調用wait方法實現。
    3.不要在synchronized方法中花費大量的時間。大多數操作只是更新數據結構,然后很快返回。如果你不能立即完成synchronized方法的操作,那么請調用wait方法,這樣你就可以在等待時釋放該對象鎖。
    4.每當一個方法改變某個對象的狀態時,太就應該調用notifyALL方法。這樣可以給等待的線程一個機會,以便查看環境有沒有發生變化。
    5.請記住,wait和notifyALL/notify方法都屬于Object類的方法,而不是Thread類的方法。請反復檢查你對wait方法的調用同一對象上的通知是否匹配。

     

     

    posted on 2008-10-19 21:23 侖波比 閱讀(202) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久亚洲精品无码AV红樱桃| 亚洲AV无码无限在线观看不卡| 未满十八18禁止免费无码网站| 亚洲国产成人在线视频| 性做久久久久免费看| 成人影片一区免费观看| 亚洲已满18点击进入在线观看| 亚洲精品第一国产综合精品99| 99re在线免费视频| 国产成人亚洲综合无| 内射少妇36P亚洲区| 四虎永久成人免费| 99久久国产免费中文无字幕| 亚洲sm另类一区二区三区| 亚洲av综合色区| 国产成人精品免费直播| 99精品热线在线观看免费视频| 亚洲AV日韩AV永久无码色欲| 亚洲人成电影亚洲人成9999网| 国产伦精品一区二区三区免费下载| 免费黄网站在线看| 狠狠热精品免费观看| 亚洲精品一卡2卡3卡三卡四卡| 亚洲国产精品一区二区九九| 日本免费网址大全在线观看| a毛片在线还看免费网站| 亚洲AV无码一区二区大桥未久| 亚洲综合亚洲国产尤物| 国产亚洲精品影视在线产品| 超pen个人视频国产免费观看| 亚洲国产精品无码久久久久久曰| 57pao一国产成永久免费| 久久久WWW免费人成精品| 欧美亚洲国产SUV| 亚洲一区二区三区精品视频| 亚洲av中文无码乱人伦在线r▽| 亚洲国产精品狼友中文久久久| 成人免费视频软件网站| 日本视频一区在线观看免费| 亚欧免费一级毛片| 野花香高清在线观看视频播放免费 |