1. 程式人生 > >由StreamWriter.WriteLine 引發對C#多執行緒的深入思考(一)

由StreamWriter.WriteLine 引發對C#多執行緒的深入思考(一)

http://blog.csdn.net/nndtdx/article/details/6789810

首先,StreamWriter執行緒安全麼?

答:StreamWriter 的構造以及StreamWriter.WriteLine(string)都是非執行緒安全的

我們封裝兩個寫日誌的方法。

底層都是由StreamWriter.writeline來實現.一個加鎖,一個不加鎖。將加鎖的那個命名為safewritelog,另一個命名為unsafeWritelog.然後利用兩個迴圈。不停的分別建立個執行緒,去寫日誌。測試看哪個會出現寫異常。程式碼如下:

[csharp]
 view plain copy  print?
  1. namespace ThreadWriteLog  
  2. {  
  3.     class Program  
  4.     {  
  5.         privatestaticobject ob = "喲內容!!";  
  6.         staticvoid Main(string[] args)  
  7.         {  
  8.             for (int i = 0; i < 10; i++)  
  9.             {  
  10.                 Thread wrtieThread = new
     Thread(SafyWriteLog);  
  11.                 wrtieThread.Name = "執行緒--" + i;  
  12.                 string content = "這是" + wrtieThread.Name + "的內容Y";  
  13.                 wrtieThread.Start(content);  
  14.             }  
  15.             for (int i = 0; i < 10; i++)  
  16.             {  
  17.                 Thread wrtieThread = new
     Thread(UnSafyWriteLog);  
  18.                 wrtieThread.Name = "執行緒¨¬--" + i;  
  19.                 string content = "這是" + wrtieThread.Name + "的內容Y";  
  20.                 wrtieThread.Start(content);  
  21.             }  
  22.             Console.WriteLine("結束");  
  23.             Console.Read();  
  24.         }  
  25.         publicstaticvoid SafyWriteLog(object  content)  
  26.         {  
  27.             string path = @"C:\SafeLog.txt";  
  28.             lock (ob)  
  29.             {  
  30.                 StreamWriter sw = File.AppendText(path);  
  31.                 sw.WriteLine(content.ToString());  
  32.                 sw.Close();  
  33.             }  
  34.         }  
  35.         publicstaticvoid UnSafyWriteLog(object content)  
  36.         {  
  37.             string path = @"C:\UnSafeLog.txt";  
  38.             StreamWriter sw = File.AppendText(path);  
  39.             sw.WriteLine(content.ToString());  
  40.             sw.Close();  
  41.         }  
  42.     }  
  43. }  


執行後,第一個for迴圈順利結束,檔案中顯示 0-9程序沒有問題。

這是執行緒--0的內容

這是執行緒--1的內容

這是執行緒--2的內容

這是執行緒--5的內容

這是執行緒--3的內容

這是執行緒--4的內容

這是執行緒--6的內容

這是執行緒--7的內容

這是執行緒--8的內容

這是執行緒--9的內容

也符合執行緒的概念,隨著系統的隨機排程而執行。

而第二個for迴圈沒有正常完成,丟擲異常

[csharp] view plain copy  print?
  1. 未處理的異常: 未處理的異常: 未處理的異常: 未處理的異常: 未處理的異常: 未處理的異  
  2. 常:       System.IO.IOException: 檔案“C:\UnSafeLog.txt”正由另一程序使用,因此  
  3. 該程序無法訪問該檔案。  
  4.    在 System.IO.__Error.WinIOError(Int32 errorCode, StringmaybeFullPath)  
  5.    在 System.IO.FileStream.Init(String path, FileMode mode,FileAccess access, I  
  6. nt32rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions o  
  7. ptions,SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)  
  8.    在 System.IO.FileStream..ctor(String path, FileMode mode,FileAccess access,  
  9. FileShareshare, Int32 bufferSize, FileOptions options)  
  10.    在 System.IO.StreamWriter.CreateFile(String path, Booleanappend)  
  11.    在 System.IO.StreamWriter..ctor(String path, Booleanappend, Encoding encodin  
  12. g, Int32bufferSize)  
  13.    在 System.IO.StreamWriter..ctor(String path, Booleanappend)  
  14.    在 System.IO.File.AppendText(Stringpath)  
  15.    在 caTestProj.Program.UnSafyWriteLog(Object content) 位置 F:\ASP.NET\MyCode\c  
  16. aTestProj\caTestProj\Program.cs:行號 51  
  17.    在 System.Threading.ThreadHelper.ThreadStart_Context(Objectstate)  
  18.    在 System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext, C  
  19. ontextCallbackcallback, Object state)  
  20.    在 System.Threading.ThreadHelper.ThreadStart(Objectobj)System.IO.IOException  
  21. : 檔案“C:\UnSafeLog.txt”正由另一程序使用,因此該程序無法訪問該檔案。  
  22.    在 System.IO.__Error.WinIOError(Int32 errorCode, StringmaybeFullPath)  


正常分析理解,

StreamWriter.WriteLine方法本身沒有執行緒同步方法,多執行緒寫日誌時(注意這裡,我們不同的執行緒使用的是不同的StreamWriter),多個執行緒同時訪問檔案,出現異常。

但是 確實是WriteLine出錯了麼?

從堆疊跟蹤來看,錯誤出現在Thread執行緒回撥UnSafyWriteLog方法出現錯誤,即執行AppendText時出錯。

在到裡邊看,構造StreamWriter物件出錯-à FileStream物件構造出錯-- 呼叫FileStream.Init出錯,最後到了win32函式winIoError.也就是構造FileStream物件時出錯。我們很明白肯定一個共享寫的問題了。

那麼,可以斷定,問題在於,呼叫File.APpendTest時,會構造StreamWriter,而這個StreamWriter是獨佔式的

由於該檔案已被另一個執行緒訪問,所以StreamWriter構造出現異常,

而並不是在StreamWriter.WriteLine上出的錯誤。

對於SafeWritelog,我們對Streamwriter的構造以及write都加了鎖,也就是說,每次構造streamWriter的時候,還是Writeline的時候,我們都保證了有唯一的物件對磁碟檔案(或者快取)進行操作。

那如果我用同一個StreamWriter呢?也就是說,Writeline本身是不是多執行緒安全的?

現在我們使用同一個Streamwriter,測試writeline的執行緒安全特性。

也就是說,如果同時有兩個執行緒同時呼叫Wtriteline方法,出現異常,則說明非執行緒安全可沒有異常,說明執行緒安全。

程式碼如下

[csharp] view plain copy  print?
  1. class Program  
  2. {  
  3.     staticobject   ob=newobject();  
  4.     staticstring path = @"C:\UnSafeLog.txt";  
  5.     privatestatic StreamWriter sw2;  
  6.     staticvoid Main(string[] args)  
  7.     {  
  8.         for (int i = 0; i < 10; i++)  
  9.         {  
  10.             Thread wrtieThread = new Thread(SafyWriteLog);  
  11.             wrtieThread.Name = "執行緒--" + i;  
  12.             string content = "這是" + wrtieThread.Name + "的內容";  
  13.             wrtieThread.Start(content);  
  14.         }  
  15.        sw2 = File.AppendText(path);  
  16.         for (int i = 0; i < 10; i++)  
  17.         {  
  18.             Thread wrtieThread = new Thread(UnSafyWriteLog);  
  19.             wrtieThread.Name = "執行緒--" + i;  
  20.             string content = "這是" + wrtieThread.Name + "的內容Y";  
  21.             wrtieThread.Start(content);  
  22.         }  
  23.          sw2.Close();  
  24.         Console.WriteLine("結束");  
  25.         Console.Read();  
  26.     }  
  27. 相關推薦

    StreamWriter.WriteLine 引發C#執行深入思考

    http://blog.csdn.net/nndtdx/article/details/6789810 首先,StreamWriter執行緒安全麼? 答:StreamWriter 的構造以及StreamWriter.WriteLine(string)都是非

    c++執行重點難點interlocked系列原子操作

    _beginthreadex()函式在建立新執行緒時會分配並初始化一個_tiddata塊。這個_tiddata塊自然是用來存放一些需要執行緒獨享的資料。事實上新執行緒執行時會首先將_tiddata塊與自己進一步關聯起來。然後新執行緒呼叫標準C執行庫函式如st

    C++執行同步技巧 ---事件

    簡介 Windows線上程控制方面提供了多種訊號處理機制,其中一種便是使用 CreateEvent() 函式建立事件,然後使用訊號控制執行緒執行。其中將事件變為有訊號可使用 SetEvent() 函式,將事件訊號復位(變為無訊號)可使用 ResetEvent(

    .net 4.0 中執行新特性

          在.net 40中對多執行緒的處理增加了很多新的類以方便多執行緒環境下的程式設計實現,首先需要了解的是兩個非常有用的類Lazy<T>和ThreadLazy<T>,通過這兩個類我們可以很方便實現一個單例模式而不用考慮太多的執行緒安全的問題。

    C++執行程式設計回顧1C11

    1、執行緒join&detach,程式碼示例如下(實測,可用): #include <iostream> #include <thread> #include <windows.h>//列印執行緒號所引,僅限Wi

    c++11執行詳解

      原文作者:aircraft 原文連結:https://www.cnblogs.com/DOMLX/p/10914162.html              最近是恰好寫了一些c++11多執行緒有關的東西,就寫一下筆記留著以後自己忘記回來看吧,也不是專門寫給讀者看的,我就想到哪就寫到哪吧 &nbs

    c++11 執行入門教程

      原文作者:aircraft 原文連結:https://www.cnblogs.com/DOMLX/p/10945309.html              最近是恰好寫了一些c++11多執行緒有關的東西,就寫一下筆記留著以後自己忘記回來看吧,也不是專門寫給讀者看的,我就想到哪就寫到哪吧

    執行詳解

    [多執行緒詳解(一)](http://www.neilx.com) 一、概念準備 1、程序 (1)直譯:正在進行中的程式 (2)解釋:執行一個程式時,會在記憶體中為程式開闢空間,這個空間就是一個程序。 (3)注意:一個程序中不可能沒有執行緒,只有有了執行緒才能執行; 程序只

    執行學習總結

    一、程序和執行緒的定義 程序:程序是資源(CPU、記憶體等)分配的基本單位,它是程式執行時的一個例項。程式執行時系統就會建立一個程序,併為它分配資源,然後把該程序放入程序就緒佇列,程序排程器選中它的時候就會為它分配CPU時間,程式開始真正執行。 執行緒:執行緒是程式執行時的最小單位,它是程序

    Java執行-基礎篇

    多執行緒---基礎篇,本文主要針對多執行緒的基礎進行復習,內容包括執行緒的理解,建立方式,Thread類函式理解; 1、執行緒的理解:OS系統角度:每個執行的程式都會被作業系統建立對應的程序(包括分配的資源、PCB等),程序是作業系統分配資源的基本單位(理解:程式執行需要空間,作業系統建立對應程序時

    Java面向物件與執行綜合實驗之封裝、繼承與

    編寫一個程式,實現檔案管理系統中的使用者管理模組。要求模組中實現使用者的模擬登入過程。通過使用者輸入,獲取使用者名稱和口令;與事先記錄在程式中的使用者資訊進行對比,通過口令驗證後才能使用系統。使用者分為系統管理人員、檔案錄入人員,檔案瀏覽人員三類,相關類圖如下所示。 (1)要求在使用者類中

    執行學習筆記

    一. 新建執行緒(兩種方法) 第一種:繼承Thread 1.定義一個類繼承Thread 2.該類重寫run方法。其中的getName是獲取執行緒名方法;有參構造可以在新建時指定執行緒名 3.建立子類物件就是建立新執行緒 4.子類物件呼叫start方法 ,開啟執行

    Java執行學習筆記之中斷中的Interrupt,interrupted(),isInterrupted()

    1、關於中斷 在Java中中斷最初是通過stop()來終止執行緒的,後來發現這樣簡單粗暴的停止執行緒會產生很多問題(例如物件monitor的釋放),所以改為deprecated,推薦使用interrupt()來中斷執行緒。而對於執行緒來說,會持有一個inter

    Java執行與併發

    多執行緒與併發的基礎問題 併發就是指程式同時處理多個任務的能力(一個程式被多個使用者訪問都能看到自己預期的結果) 併發的根源在於對多工情況下訪問資源的有效控制! 併發背後的問題 public class DownloadSimple {

    Java執行乾貨系列—Java執行基礎

    多執行緒併發程式設計是Java程式設計中重要的一塊內容,也是面試重點覆蓋區域,所以學好多執行緒併發程式設計對我們來說極其重要,下面跟我一起開啟本次的學習之旅吧。 正文 執行緒與程序 1 執行緒:程序中負責程式執行的執行單元 執行緒本身依靠程式進行執行 執行緒是程式中的順序控制流,只能使用分配給程式的資源和環

    執行基礎知識 執行的概念及建立任務與執行

    執行緒的概念及建立任務與執行緒 引言 多執行緒使得程式中的多個任務可以同時執行。 java的重要功能之一就是內部支援多執行緒————在一個程式中運行同時執行多個任務。在許多程式設計語言中,多執行緒都是通過呼叫依賴於系統的過程或函式來實現的。在本文中,將介紹執行緒的該

    Java執行--Monitor物件

    1. 什麼是Monitor?     Monitor其實是一種同步工具,也可以說是一種同步機制,它通常被描述為一個物件,主要特點是: 物件的所有方法都被“互斥”的執行。好比一個Monitor只有一個執行“許可”,任一個執行緒進入任何一個方法都需要獲得這個“許可”,離開時

    【JAVA秒會技術之玩轉執行執行那些事兒

    多執行緒那些事兒(一) 現在只要出去面試,關於“Java多執行緒”的問題,幾乎沒有一家單位不問的,可見其重要性。於是博主抽空研究了一下,確實很有意思!以下是我綜合整理了網上的各種資料,和個人的一些理解,寫的一篇總結博文,僅供學習、交流。 (一)多執行緒的概念      

    Qt執行程式設計總結

    Qt對執行緒提供了支援,基本形式有獨立於平臺的執行緒類、執行緒安全方式的事件傳遞和一個全域性Qt庫互斥量允許你可以從不同的執行緒呼叫Qt方法。 這個文件是提供給那些對多執行緒程式設計有豐富的知識和經驗的聽眾的。推薦閱讀: 警告:所有的GUI類(比如,QWidget和它的

    Qt執行程式設計總結所有GUI物件都是執行不安全的

    Qt對執行緒提供了支援,基本形式有獨立於平臺的執行緒類、執行緒安全方式的事件傳遞和一個全域性Qt庫互斥量允許你可以從不同的執行緒呼叫Qt方法。 這個文件是提供給那些對多執行緒程式設計有豐富的知識和經驗的聽眾的。推薦閱讀: 警告:所有的GUI類(比如,QWidget和它的子類),作業系統核心類(比如,QPr