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

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


    網站導航:
     
    主站蜘蛛池模板: 亚洲爆乳无码精品AAA片蜜桃| jizz免费在线观看| 亚洲精品国产日韩| 亚洲AV成人一区二区三区观看 | 亚洲一区二区三区在线观看精品中文| 亚洲乱码中文字幕综合| 久久久久亚洲av无码尤物| gogo免费在线观看| 日韩精品亚洲aⅴ在线影院| 搡女人免费免费视频观看| 亚洲国产精品无码成人片久久 | 国产va免费精品观看精品 | 麻豆亚洲AV永久无码精品久久| 中文字幕无码毛片免费看| 亚洲夜夜欢A∨一区二区三区| 男人都懂www深夜免费网站| 国产一级淫片a免费播放口之| 国产成人综合亚洲| 美女网站免费福利视频| 亚洲性色精品一区二区在线| 99久久精品免费视频| 亚洲综合另类小说色区色噜噜| 亚洲午夜一区二区电影院| 毛片免费观看视频| 亚洲区日韩精品中文字幕| 亚洲毛片在线免费观看| 国产精品亚洲片在线| 在线观看免费av网站| 亚洲人成网站999久久久综合| 四虎影视永久免费观看网址| 精品97国产免费人成视频| 亚洲色成人网一二三区| 女性无套免费网站在线看| 色www永久免费网站| 成人亚洲国产va天堂| 国产精品亚洲产品一区二区三区 | 久久99热精品免费观看牛牛| 亚洲一区在线视频观看| 99久久99久久精品免费观看| 亚洲乱亚洲乱妇24p| 国产精品久久久亚洲|