<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)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 国产日韩久久免费影院| 97国产免费全部免费观看| 一区二区免费视频| 亚洲AV成人一区二区三区在线看| 成人A片产无码免费视频在线观看| 国产精品亚洲αv天堂无码| 日韩免费无码一区二区三区| 国产亚洲精品va在线| 免费在线看v网址| 污污的视频在线免费观看| 亚洲最大成人网色| 免费在线观看黄网站| 日本免费一区二区三区| 美女无遮挡免费视频网站| 亚洲综合综合在线| 亚洲毛片在线免费观看| 日日摸夜夜添夜夜免费视频| 亚洲六月丁香六月婷婷色伊人 | 日本免费人成网ww555在线| 亚洲依依成人亚洲社区| 亚洲av无码不卡一区二区三区| 人妻丰满熟妇无码区免费 | 亚洲午夜在线电影| 免费国产a国产片高清网站| 精品无码免费专区毛片| 亚洲av无码久久忘忧草| 在线亚洲97se亚洲综合在线| 成全影视免费观看大全二| 久久久免费精品re6| 国产高清对白在线观看免费91 | 久久亚洲免费视频| 国产jizzjizz视频全部免费| 在线播放国产不卡免费视频| 亚洲小说区图片区另类春色| 日本最新免费不卡二区在线| 成人免费AA片在线观看| 久9这里精品免费视频| 中出五十路免费视频| 免费毛片毛片网址| 精品久久久久久久久亚洲偷窥女厕| 亚洲国产小视频精品久久久三级 |