<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ù)實際運行的多線程應用程序中,二個或多個線程需要共享對同一對象的訪問。如果二個線程訪問同一個對象,并且每個線程抖調(diào)用同一個方法,以便修改該對象的狀態(tài),那將出現(xiàn)什么樣的情況呢?
            書中最常見的例子就是銀行取款的例子。假如一個人在銀行里開了10個帳戶,外面設(shè)置10個線程,每個帳戶一個線程。每個交易事務負責將一筆隨機數(shù)額的資金從該線程服務的帳戶轉(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ù)不應該被鎖定。調(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)出項變更,那么它應該在對象的內(nèi)部等待,而不是在外邊等待,這可以通過輸入一個synchronized方法,并調(diào)用wait方法實現(xiàn)。
    3.不要在synchronized方法中花費大量的時間。大多數(shù)操作只是更新數(shù)據(jù)結(jié)構(gòu),然后很快返回。如果你不能立即完成synchronized方法的操作,那么請調(diào)用wait方法,這樣你就可以在等待時釋放該對象鎖。
    4.每當一個方法改變某個對象的狀態(tài)時,太就應該調(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)站導航:
     
    主站蜘蛛池模板: AV激情亚洲男人的天堂国语| 国产 亚洲 中文在线 字幕| 国产精品亚洲综合一区在线观看| 免费看黄网站在线看| 久久精品免费观看| 久久亚洲高清综合| 中国性猛交xxxxx免费看| 亚洲婷婷国产精品电影人久久| 日韩在线视频免费| 中文字幕亚洲一区二区三区| a一级爱做片免费| 99久久免费国产精品特黄| 亚洲同性男gay网站在线观看| 五月亭亭免费高清在线| 亚洲AV色吊丝无码| 日韩免费在线观看| 免费无遮挡无遮羞在线看| 亚洲日本一区二区三区在线不卡| 久久性生大片免费观看性| 亚洲成色WWW久久网站| 亚洲av成人一区二区三区在线播放| 最好免费观看韩国+日本| 久久久久久久综合日本亚洲| 免费的全黄一级录像带| 亚洲大香人伊一本线| 国产小视频在线免费| 精品无码国产污污污免费网站国产| 亚洲AV无码国产丝袜在线观看| 久久久久久夜精品精品免费啦| 成人免费激情视频| 亚洲精品无码专区| 思思re热免费精品视频66| 国产成人A人亚洲精品无码| 四虎精品视频在线永久免费观看| 天堂亚洲国产中文在线| av在线亚洲欧洲日产一区二区| 精品一区二区三区免费毛片爱 | 丰满少妇作爱视频免费观看| 毛片a级三毛片免费播放| 中文字幕亚洲精品资源网| 免费网站观看WWW在线观看|