asp.net中關於靜態變量的生命周期和線程安全以及一些類中的定義靜態變量的概念


public class StaticDictory
    {
      public static Dictionary<int, string> CataLog;
      public static Dictionary<int, string> RoleName;
      public int A;
      public StaticDictory()
      {
          this.A = 5;
      }
      public StaticDictory(int B)
      {
          this.A = B;
      }
      static  StaticDictory()
      {
          CataLog = new Dictionary<int, string>();
          CataLog.Add(1, "瑜伽部落");
          CataLog.Add(2, "自行車部落");
          CataLog.Add(3, "大學生部落");
          RoleName = new Dictionary<int, string>();
          RoleName.Add(1, "導師經銷商");
          RoleName.Add(2, "加盟經銷商");
          RoleName.Add(3, "金牌銷售代表");
          RoleName.Add(4, "銀牌銷售代表");
          RoleName.Add(5, "戰略合作伙伴");
          RoleName.Add(6, "加盟經銷商");
          RoleName.Add(7, "練習者");
          RoleName.Add(8, "管理員");
          RoleName.Add(9, "超級管理員");
          RoleName.Add(10, "生產線管理員");
          RoleName.Add(11, "財務管理員");
          RoleName.Add(12, "總經理管理員");
          RoleName.Add(13, "總經理助理管理員");
          RoleName.Add(14, "銷售協議結構");
          RoleName.Add(15, "明星銷售代表");
          RoleName.Add(16, "普通會員");
          RoleName.Add(17, "普通會員");
          RoleName.Add(18, "大學生首領");
          RoleName.Add(19, "學生組織");
          RoleName.Add(20, "大學生銷售代表");
      }
    }
 
在類中只能定義一個靜態的構造函數,是在創建第一個類實例或任何靜態成員被引用時,.NET將自動調用靜態構造函數來初始化類,也就是說我們無法直接調用靜態構造函數,也就無法控制什么時候執行靜態構造函數了,他的生命周期下面有介紹。靜態函數只能調用和初始化靜態成員。實例化函數可以調用靜態成員和實例化成員。同理靜態函數不能調用實例化函數,實例化函數可以調用靜態函數和實例化函數。
 
別的函數需要實例化,StaticDictory AA=new StaticDictory(6);實例話了對象,才可以調用實例化成員,類不寫構造函數的話會有默認構造函數。
文章來自: 好喜愛學習網( http://www.haoxiai.net/) 網址: http://www.haoxiai.net/bianchengyuyan/aspnetbiancheng/82327.html asp.net中關於靜態變量的生命周期和線程安全

本來我理解的靜態變量的生命周期是

    void Application_Start開始

    void Application_End結束的,本來這就是對的

今天要做一個全局的應用,想確認一下,在網上一找,我的天,說什么的都有

大概分三種

1.Application_Start——Application_End

2.Session_Start——Session_End

3.類生命周期結束

 

我用4個機器做了一個測試發現靜態變量值一直是不變的,並沒有因為其它用戶登錄而被銷毀,確認應該是Application級的

 

靜態類在首次訪問時會調用靜態構造器創建類類型對象,類型對象的生存周期是整個應用程序域的生存周期,也就說被訪問過的靜態類,只有它所在的應用程序域被卸載時才會被卸載。

類的成員分為兩類,靜態成員(static member)和實例成員(instance member)。靜態成員屬於類,實例成員則屬於對象,即類的實例。

    簡單討論一下在一個類中使用靜態字段(static field)和靜態方法(static method)是否會有線程安全問題。 

    我們在知道, 靜態字段(static field)和靜態方法(static method)的調用是通過類來調用。靜態方法不對特定的實例操作,只能訪問靜態成員。實例方法可對特定的實例操作,既能訪問靜態成員,也能訪問實例成員。

    那么,在多線程中使用靜態方法是否有線程安全問題?這要看靜態方法是是引起線程安全問題要看在靜態方法中是否使用了靜態成員。

    因為,在多線程中使用同一個靜態方法時,每個線程使用各自的實例字段(instance field)的副本,而共享一個靜態字段(static field)。所以說,如果該靜態方法不去操作一個靜態成員,只在方法內部使用實例字段(instance field),不會引起安全性問題。但是,如果該靜態方法操作了一個靜態字段,則需要靜態方法中采用互斥訪問的方式進行安全處理。
   
    舉個簡單的例子,我們使用的Console.WriteLine();中WriteLine()是Console.WriteLine類的靜態方法。

     對於ASP.NET, 多個客戶端訪問服務器端, 這是一個多線程的例子.只要理解了原因,我們可以在三層架構中的數據訪問層中放心使用靜態方法(static method)來訪問數據庫.

 

靜態方法如果沒有使用靜態變量,則沒有線程安全問題。

為什么呢?因為靜態方法內聲明的變量,每個線程調用時,都會新創建一份,而不會共用一個存儲單元。每個線程都會創建自己的一份,因此不會有線程安全問題

 

注意,靜態變量,由於是在類加載時占用一個存儲區,每個線程都是共用這個存儲區的,所以如果在靜態方法里使用了靜態變量,這就會有線程安全問題!

FeedBack:
2009-05-24 22:55 | merry05[未注冊用戶]
今天也遇到這個問題,就利用google到你這兒了

但這樣還有一個問題static變量為application級別的,那這個變量所存儲的值能在多個用戶之間共享嗎?如果多個用戶都想使用這個值,那如何做到互斥?

在Application中有個lock()的操作,而普通的static卻沒有!

  回復  引用    
#2樓 [ 樓主]
2009-05-25 11:12 | 宏宇       
當然是共享的,就因為他是比較單一的共享,沒有什么自己的方法,所以一般都用在經常用但是只讀的字段
  回復  引用  查看    
2009-05-26 20:12 | merry05[未注冊用戶]
謝謝你的回復

經過這幾天的查找,得知可以加了static mutex來實現互斥

  回復  引用    
2009-05-27 16:45 | siso[未注冊用戶]
請問下博主,Asp.net中,我在一自定義類 聲明一靜態變量
然后在Default的Button1中讀取。

我是發布網站后在IIS試驗的

當我把所有打開的瀏覽器窗口關閉后,再訪問Default,仍然可訪問到該靜態變量,甚至把IIS停止再開始 ,仍然可以訪問靜態變量。
直到重啟計算機才讀不到靜態變量。

我想了解的是Application_End到底什么時候才會執行。謝謝!

  回復  引用    
#5樓 [ 樓主]
2009-05-28 14:00 | 宏宇       
1、Application_Start:這個事件被請求一次后,只要你不重新啟動IIS以后就再也不出發了。(有時不然,有待討論)
Application_BeginRequest:這個事件每次請求后都觸發,即使在同一個瀏覽器中刷新也不例外。
Application_AuthenticateRequest:每次請求都被觸發。
Session_Start:這個事件跟瀏覽器實例相關,每次打開一個新瀏覽器時被觸發。
Application_EndRequest:跟BeginRequest時間一樣,只是觸發順序不同。
Session_End:session過期或用戶調用Session.Abandon()結束會話時觸發。
Application_End:停止iis時在iis尚未被停止之前被觸發。
Application.Error:提供一種在應用程序級處理錯誤的方式。所有錯誤都可以從頁面“冒泡”到應用程序級,在這里面你可以將錯誤寫入日志或轉向其他頁面。

  回復  引用  查看    
#6樓 [ 樓主]
2009-05-28 14:02 | 宏宇       
Application_End停止iis或者IIs重啟時觸發和客戶端沒有關系
  回復  引用  查看    
2009-06-01 15:02 | siso[未注冊用戶]
謝謝回復,但還是有些不太明白

Application_End:停止iis時在iis尚未被停止之前被觸發。
----------------------------------------------

IIS 的停止是指得停止服務還是在IIS管理器點那個停止就可以了?
我是在服務器的IIS管理器點那個四方形的停止的。

這時應該Application_End會觸發吧,可是好像沒有觸發


-----------------------------------------
Application_End停止iis或者IIs重啟時觸發和客戶端沒有關系
-----------------------------------------
我想既然靜態變量是保存在服務端的,而且上面您的文章有提到靜態變量的結束周期是在Application_End觸發時。

那么我想只要在服務器端停止IIS,那么我在客戶端(讀取服務器的生成)應該就訪問不到該靜態變量了,可是事實是仍然訪問得到。謝謝!

  回復  引用    
#8樓 [ 樓主]
2009-06-01 16:36 | 宏宇       
暈 ,你在客戶端得到靜態變量的時候,應用程序肯定是已經開啟了,要不程序你也沒辦法訪問
  回復  引用  查看    
#9樓 [ 樓主]
2009-06-01 16:43 | 宏宇       
Application_End是指應用你這個程序結束時觸發的,和IIS結束沒有關系,只不過是IIS結束引起了你的應用程序結束
注:你在Application_End事件設斷點,然后重啟IIS服務,如果這個Web程序發布在IIS上,那么這個事件將被觸發

  回復  引用  查看    
2009-06-02 13:59 | siso[未注冊用戶]
--引用--------------------------------------------------
宏宇: Application_End是指應用你這個程序結束時觸發的,和IIS結束沒有關系,只不過是IIS結束引起了你的應用程序結束
注:你在Application_End事件設斷點,然后重啟IIS服務,如果這個Web程序發布在IIS上,那么這個事件將被觸發
--------------------------------------------------------


我的WEB是發布在IIS中了,假設我Default中原靜態變量a值為10
Button1改變a的值為20, Button2讀取並顯示該變量。
即如果我點擊button1后,再Button2,應該顯示20
我想了解的是,在點擊Button1之后,什么情況下,Button2仍然顯示原來的值10。

跟據你上面的文章,如果我沒有理解錯的話應是該靜態變量周期結束時。
而靜態變量結束周期==Application_End==IIS重啟

所以我IIS重啟后,理論上重新打開瀏覽器,按Button2,應該顯示的值為10,而不是20.但事實是IIS重啟后,仍然顯示20. 即靜態變量周期仍沒有結束。
所以…………
謝謝!



  回復  引用    
#11樓 [ 樓主]
2009-06-03 11:22 | 宏宇       
public class Class1
{
public static string w;
public Class1()
{
//
// TODO: Add constructor logic here
//
}
}
<html xmlns="http://www.w3.org/1999/xhtml%22%3E
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</div>
</form>
</body>
</html>

protected void Page_Load(object sender, EventArgs e)
{
string www = Class1.w;
}
protected void Button1_Click(object sender, EventArgs e)
{
Class1.w = "1";
}

流程:
1.運行程序string www=null
2.點擊button,string www="1"
3.重啟IIS
4.關閉當前頁面(此時不要操作頁面了,一操作就又啟動了)
5.再啟動程序(應用程序的內存空間重新創建)
6.string www=null

  回復  引用  查看    
2010-01-06 22:37 | ASTAR Coming Now       
在多線程應用場景里面,在靜態方法中,如果不是用靜態變量,那么操作應該是沒有問題,這點可以確認。

那么,使用靜態變量的方法呢?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace Dottext.Framework.Providers
{
     /// <summary>
     /// Summary description for DTOProvider.
     /// </summary>
  
     public class DTOProvider
     {
         private DTOProvider(){}
  
         static DTOProvider()
         {
             DTOProviderConfiguration dtoPC = Config.Settings.BlogProviders.DTOProvider;
             idto = (IDTOProvider)dtoPC.Instance();
         }
  
         private static IDTOProvider idto = null ;
         public static IDTOProvider Instance()
         {
             return idto;
         }
     }
}


上面代碼可見
idto是一個靜態變量。
我們會去使用idto的方法,假設idto的類定義有方法foo
要保證不出現訪問沖突。
foo方法內都不能操作靜態變量和成員變量?
(可以訪問但不能寫)

我的理解是否正確?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM