2014-09-25 24 views
0

我讀/從會話在不同的線程在單個請求編寫對象是這樣的:從pro-pro會話中讀取/寫入對象是否是原子操作?

public class HomeController : Controller 
{ 
    public int Index() 
    { 
     Task.WaitAll(DoStuff(), DoMoreStuff()); 
     var foo = Session["foo"] as Foo; 
     return foo.MyProperty; 
    } 

    public Task DoStuff() 
    { 
     return Task.Factory.StartNew(() => 
     { 
      var foo = Session["foo"] as Foo; 
      if (foo == null || foo.MyProperty == 1) 
       foo = new Foo { MyProperty = 1 }; 
      Session["foo"] = foo; 
     }); 
    } 

    public Task DoMoreStuff() 
    { 
     return Task.Factory.StartNew(() => 
     { 
      var foo = Session["foo"] as Foo; 
      if (foo == null || foo.MyProperty == 1) 
       foo = new Foo { MyProperty = 2 }; 
      Session["foo"] = foo; 
     }); 
    } 
} 

public class Foo 
{ 
    public int MyProperty { get; set; } 
} 

現在,在這個代碼的邏輯顯然是沒有意義的,但我提供它來顯示什麼樣的操作我做:

  • 閱讀對象的引用,
  • 寫作對象的引用,
  • 創建新的對象,
  • 閱讀OBJ等領域。

我沒有修改現有的對象。一般來說,這段代碼是否會損壞會話狀態或內存?

這是具有默認進程內會話實現的ASP.NET MVC應用程序。

如果此代碼可能損壞會話狀態,每次我在此代碼中訪問會話時,是否應鎖定Session.SyncRoot

回答

1

讀取和寫入引用是原子的,但在這種情況下沒有意義,因爲HttpSessionState類不是線程安全的。

如果一個線程在會話狀態中設置了一個項目,而另一個線程同時獲取或設置了一個項目,則該實例可能會損壞。這會使其行爲不正常或導致崩潰。

所以,是的,如果你想對來自不同線程的會話狀態做任何事情,所有訪問都需要在代碼塊中使用SyncRoot屬性(或者你自己的對象,如果你喜歡的話)鎖定。


HttpSessionState class的文檔包含此標準宣佈:

「任何公共靜態(在Visual Basic中共享)此類型的成員 線程安全的所有實例成員都是不保證。線程 安全。「

這意味着靜態成員是線程安全的,因爲他們不會做任何事情來專門中斷線程安全,並且實例成員不會做任何事情來確保線程安全。這根本不是爲了線程安全而設計的。