<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      線程是CPU資源調(diào)度的基本單位,如果一個程序中只有一個線程,則最多只能在一個處理器上運行,如果電腦/服務(wù)器是雙處理器系統(tǒng),則單線程的程序只能使用一半的CPU資源,所以,多線程是提高處理器資源利用率的重要方法。比如web系統(tǒng)中的servlet容器,它處理請求時會針對每一個請求創(chuàng)建一個線程調(diào)用servlet的service方法(https://m.runoob.com/servlet/servlet-life-cycle.html),servlet的實例在容器中只會創(chuàng)建一個,所以就涉及到了并發(fā)操作問題(多個線程訪問處理同一個資源),下圖摘自菜鳥教程中給出的一個請求示例:

       

       

       從上圖中可以看出,如果service()方法對某一個可變的公共變量做了操作,線程a,b,c如果未作合適的同步控制的話,程序必然會出現(xiàn)錯誤,修復(fù)這個問題有三種方式:

      a.不在線程之間共享該狀態(tài)變量,也就是service()方法不會調(diào)用公共的變量/資源。

      b.將狀態(tài)變量設(shè)置為不可修改的變量,也就是service()方法調(diào)用的公共變量的值是一個恒定的值,各個線程也不能對該變量進(jìn)行修改。

      c.在訪問公共的狀態(tài)變量時進(jìn)行同步控制,也就是線程b/c要等線程a對公共變量的操作執(zhí)行完畢之后才能獲取訪問權(quán)。

      一個無狀態(tài)的對象一定是線程安全的,如下示例:

      package main;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class StatelessFactorizer implements Servlet {
          @Override
          public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
              int id=(int)req.getAttribute("id");
              id++;
              req.setAttribute("id",id);
          }    
          @Override
          public void init(ServletConfig config) throws ServletException {
              
          }
      
          @Override
          public ServletConfig getServletConfig() {
              return null;
          }
      
          @Override
          public String getServletInfo() {
              return null;
          }
      
          @Override
          public void destroy() {
      
          }
      }
      View Code

      上面的代碼中,id雖然做了++操作,但是它是屬于方法的內(nèi)部變量,也是線程私有的,這個值是從前端帶過來的,所以這是一中“無狀態(tài)的”操作方法。

      package main;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class UnsafeCounting implements Servlet {
          private long count=0;
          @Override
          public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
              count++;
              req.setAttribute("count",count);
          }
          @Override
          public void init(ServletConfig config) throws ServletException {
      
          }
      
          @Override
          public ServletConfig getServletConfig() {
              return null;
          }
      
          @Override
          public String getServletInfo() {
              return null;
          }
      
          @Override
          public void destroy() {
      
          }
      }
      View Code

      再如上面的示例,UnsafeCounting實例的service方法由多個線程調(diào)用時,每個線程都會操作count這個公共資源,但是count++這種操作方法并不是原子性的,所以這種操作不是線程安全的。這里定義一個術(shù)語:

      競態(tài)條件(Race Condition):并發(fā)編程時,由于不恰當(dāng)?shù)膱?zhí)行時序而出現(xiàn)不正確的結(jié)果的情況。

      對于有競態(tài)條件出現(xiàn)的情況下,需要使用“加鎖機制”來保證操作步驟的原子性,也就是多個線程對操作步驟的順序執(zhí)行,java提供了一種內(nèi)置的鎖機制來實現(xiàn)原子操作:同步代碼塊(synchronized block),同步代碼塊由兩部分組成:

      a.加鎖的對象,是一個引用,也就是說對哪個對象進(jìn)行加鎖,確定了加鎖的對象,所有的線程要先拿到這個對象的鎖才能進(jìn)行下一步的操作

      b.由該鎖保護(hù)的代碼塊,也就是哪些操作步驟必須是原子操作,就將這些需要作為原子操作的步驟放到鎖所保護(hù)的代碼塊種即可

      如下示例:

      synchronized(obj){//todo 需要是原子操作的步驟}

      **鎖的重入**

      重入是一個重要特征,就是一個線程獲取到了某個鎖的執(zhí)行權(quán),它再次獲取該鎖時,需要保證能夠獲取成功,

       

      package main;
      
      public class Widget {
      
          public synchronized void doSomething(){
              System.out.println("Widget doSomething "+this);
          }
      
          public static void main(String[] args) {
              LoggingWidget loggingWidget=new LoggingWidget();
              loggingWidget.doSomething();
          }
      }
      
      class LoggingWidget extends Widget{
          @Override
          public synchronized void doSomething() {
              System.out.println("LoggingWidget doSomething "+this);
              super.doSomething();
          }
      }
      ---------輸出--------
      LoggingWidget doSomething main.LoggingWidget@74a14482
      Widget doSomething main.LoggingWidget@74a14482
      View Code

       

      上面的代碼中,synchronized方法修飾的是非靜態(tài)方法,它的鎖對象是this,也就是方法調(diào)用所在的對象,如果synchronized放到靜態(tài)方法上,則其加鎖的對象是Class對象;從上面的打印中,super中輸出的this和子類中輸出的this是一樣的,如果synchronized鎖不能重入的話,子類在調(diào)用doSomething的時候已經(jīng)獲取到了“main.LoggingWidget@74a14482”的鎖,就不能調(diào)用super.doSomething()了,顯然是不合理的;鎖的重入則很完美地避免了該問題的產(chǎn)生。

      是不是為了簡單起見,直接將synchronized加到方法上得了?當(dāng)然不是,因為還要考慮性能問題,如下實例:

      class DownLoadFile extends HttpServlet{
          @Override
          protected synchronized void service(HttpServletRequest req,
                                 HttpServletResponse resp) throws ServletException, IOException {
              //todo 下載一個大文件
              File file=new File("c:/xxxx/uuu");
                     
              //todo 對某個公共資源進(jìn)行操作
          }
      }
      View Code

      上面的代碼中,下載大文件的操作比較費時,如果對方法進(jìn)行加鎖,則性能很差,這時候可以不對下載大文件進(jìn)行加鎖,如下:

      class DownLoadFile extends HttpServlet{
          @Override
          protected  void service(HttpServletRequest req,
                                 HttpServletResponse resp) throws ServletException, IOException {
              //todo 下載一個大文件
              File file=new File("c:/xxxx/uuu");
              synchronized(this){
                  //todo 對某個公共資源進(jìn)行操作
              }        
          }
      }
      View Code

      上面的代碼中,性能將會提升很多,因為每個請求可以發(fā)送請求后立馬進(jìn)行文件下載操作,文件下載完畢后再嘗試獲取鎖對公共資源進(jìn)行操作。

      以上是Java線程安全性的總結(jié),在保證安全的同時也需要考慮性能問題,因此加鎖時需要做到:

      a.識別哪些操作步驟需要是原子性操作,以保證程序的安全性

      b.判斷哪些操作比較費時,這些比較費時的操作一定不要持有鎖,因為會嚴(yán)重影響程序性能,記住,只對需要加鎖的步驟進(jìn)行加鎖就可以了

      posted on 2022-04-05 10:36  Judy518  閱讀(63)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 成人午夜av在线播放| 国产成人综合色就色综合| 天天看片视频免费观看| 亚洲精品乱码久久久久久按摩高清| 亚洲一区二区三区在线观看播放| 四虎国产成人永久精品免费| 国产91丝袜在线播放动漫| 日韩区中文字幕在线观看| 慈溪市| 久久国产精品夜色| 精品精品国产自在97香蕉| 国产成人无码AV片在线观看不卡| 亚洲欧美综合精品成人网站| 久久狠狠高潮亚洲精品| 亚洲av乱码一区二区| 在线视频中文字幕二区| 亚洲中文字幕在线二页| 日韩精品亚洲精品第一页| 99久久免费只有精品国产| 亚洲熟少妇一区二区三区| 国产精品理论片在线观看| 又黄又爽又色的少妇毛片| 特黄aaaaaaa片免费视频| 亚洲欧美综合人成在线| 欧美日韩国产图片区一区| 久久不见久久见www日本| 亚洲美女被黑人巨大在线播放| 黑人大战欲求不满人妻| 国产极品尤物粉嫩在线观看| 欧美人妻在线一区二区| 午夜DY888国产精品影院| 国产精品日韩av一区二区| 717午夜伦伦电影理论片| 阜新市| 国产99精品成人午夜在线| 亚洲最大成人在线播放| 亚洲国产精品久久久天堂麻豆宅男 | 人妻少妇| 国产超碰无码最新上传| 亚洲精品久久麻豆蜜桃| 永久免费av无码网站直播|