<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

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

     

    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;
       

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

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

     

     

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

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


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 成年大片免费视频| 亚洲国产精品免费在线观看| 全免费A级毛片免费看网站| 亚洲色偷偷av男人的天堂| 蜜桃成人无码区免费视频网站| 亚洲熟妇av一区二区三区漫画| 巨胸喷奶水www永久免费| 国产精品亚洲片在线观看不卡| 99免费在线视频| 亚洲国产精品无码久久一线| 中文在线免费视频| 亚洲国产精品无码专区| 免费成人高清在线视频| 97久久精品亚洲中文字幕无码 | 亚洲AV无码乱码在线观看富二代 | 亚洲AV无码一区东京热| 久久久久久久岛国免费播放| 亚洲大片在线观看| 91精品国产免费久久久久久青草| 亚洲videos| 又大又硬又爽免费视频| 久久成人永久免费播放| 亚洲成人在线网站| 国产免费毛不卡片| 国产成人亚洲精品无码AV大片| 亚洲国产黄在线观看| 国产一级片免费看| 亚洲制服丝袜在线播放| 日韩a级毛片免费视频| 久久免费99精品国产自在现线| 亚洲av网址在线观看| 成年性羞羞视频免费观看无限 | 一个人免费观看www视频| 亚洲成在人天堂在线| 韩国日本好看电影免费看| 国产高清不卡免费视频| 亚洲大尺码专区影院| 国产免费女女脚奴视频网| 国产精品亚洲精品日韩已满| 2020久久精品亚洲热综合一本| 91在线视频免费91|