成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談.NET開發中多線程思維方式

開發 后端
前段時間仔細看過些關于多線程方面的資料,項目中用到線程的地方也不少,可是,當看了Jeffrey的一篇關于鎖的文章后,發現自己雖然一直都在使用多線程,但是缺少了做多線程編程需要的思維!所以想從Jeffrey的Optex(鎖)入手,來談談我從其中體會的東西。

在NET中,我們用的最多的鎖機制就是lock,用起來很簡單,短短幾行程序就可以實現,例如:

Lock 's Code
public class TestThreading
{
    private System.Object lockThis = new System.Object();
    public void Function()
    {
        lock (lockThis)
        {
            // Access thread-sensitive resources.
        }
    }
}

其實我們也明白,lock并不是鎖,而是MS提供的一個簡便式的寫法,真正實現的是Monitor類中的Enter和Exit方法,既然提到了Monitor類也就說下有個需要注意的地方:

Pulse和PulseAll方法,這兩個方法就是把鎖狀態將要改變的消息通知給等待隊列中的線程,不過這時如果等待隊列中沒有線程,那么該方法就會一直等待下去,直到有等待的線程進入隊列,也就是說該方法可能造成類試死鎖的情況出現。

上面的lock + 線程(Thread和ThreadPool) = 多線程編程(N%)!?

對于該公式我曾經的N是80,現在是20。其中有很多東西影響我,讓我從80->20,下面的Optex就是一個入口點。

--------------------------------------------------------------------------------

Optex 's Code
public sealed class Optex : IDisposable {
   private Int32 m_Waiters = 0;
   private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);

   public Optex() { }
   public void Dispose() {
      if (m_WaiterLock != null)
      {
         m_WaiterLock.Close();
         m_WaiterLock = null;
      }
   }

   public void Enter() {
      Thread.BeginCriticalRegion();
      // Add ourself to the set of threads interested in the Optex
      if (Interlocked.Increment(ref m_Waiters) == 1) {
         // If we were the first thread to show interest, we got it.
         return;
      }

      // Another thread has the Optex, we need to wait for it
      m_WaiterLock.WaitOne();
      // When WaitOne returns, this thread now has the Optex
   }

   public void Exit() {
      // Subtract ourself from the set of threads interested in the Optex
      if (Interlocked.Decrement(ref m_Waiters) > 0) {
         // Other threads are waiting, wake 1 of them
         m_WaiterLock.Release(1);
      }
      Thread.EndCriticalRegion();
   }
}

看完上面的代碼,讓我增加了兩點認識:

1、Thread.BeginCriticalRegion()和Thread.EndCriticalRegion();        

因為這段時間正好看了一本多線程編程的書,既然將上面方法認為是進入臨界區和退出臨界區,對于臨界區而言,進入該區的數據,在沒有退出之前,如果臨界區外的程序需要使用它,那么就必須出于等待。所以覺得已經使用臨界區,為什么還要使用Semaphore?!

可是,MS只是取了個相同的名字,做的事情完全不同,上面兩個方法完全沒有臨界區的概念,它只是設置一個區域(Begin到End之間),表示該區域內發生線程中斷或未處理的異常會影響整個應用程序域。

2、m_Waiters的作用

一開始以為在Enter的時候,直接寫上:

m_WaiterLock.WaitOne();

Exit的時候,寫上:

m_WaiterLock.Release(1); 

這樣就可以了。m_Waiters有什么意義?!           

優化性能,Semaphore是內核對象,我們都知道,要盡量少的進入內核模式,因為這是很消耗性能,所以盡量少的使用內核對象。m_Waiters的意義就在這里,如果只有一個線程使用該鎖對象的時候,是不需要去獲取和釋放的。 OK,上述的東西都是鋪墊,鋪完了也就進入主題了!

多線程的思維

優化的Optex 


namespace ThreadConcurrent.Lock
{
    public sealed class Optex : IDisposable
    {
        ///
        /// 瑣的狀態
        ///

        private Int32 m_LockState = c_lsFree;

        ///


        /// 自由狀態
        ///

        private const Int32 c_lsFree = 0x00000000;
       
        ///
        /// 被擁有狀態
        ///

        private const Int32 c_lsOwned = 0x00000001;
       
        ///
        /// 等待的線程數
        ///

        private const Int32 c_1Waiter = 0x00000002;

        private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue);

        #region 構造函數

        ///


        ///
        ///

        public Optex() { }

        #endregion

        ///


        /// 請求鎖
        ///

        public void Enter()
        {
            Thread.BeginCriticalRegion();
            while (true)
            {
                Int32 ls = InterlockedOr(ref m_LockState, c_lsOwned);

                //自由狀態
                if ((ls & c_lsOwned) == c_lsFree) return;

                // 增加等待的線程數
                if (IfThen(ref m_LockState, ls, ls + c_1Waiter))
                {
                    m_WaiterLock.WaitOne();
                }
            }
        }

        public void Exit()
        {
            // 釋放瑣
            Int32 ls = InterlockedAnd(ref m_LockState, ~c_lsOwned);

            //無等待的線程
            if (ls == c_lsOwned)
            {
            }
            else
            {
                ls &= ~c_lsOwned;
                if (IfThen(ref m_LockState, ls & ~c_lsOwned, ls - c_1Waiter))
                {
                    m_WaiterLock.Release(1);
                }
                else
                {
                }
            }
            Thread.EndCriticalRegion();
        }

        #region 原子化操作

        ///


        /// 與操作
        ///

        ///
        ///
        ///
        private static Int32 InterlockedAnd(ref Int32 target, Int32 with)
        {
            Int32 i, j = target;
            do
            {
                i = j;
                j = Interlocked.CompareExchange(ref target, i & with, i);
            } while (i != j);
            return j;
        }

        ///


        /// 或操作
        ///

        ///
        ///
        ///
        private static Int32 InterlockedOr(ref Int32 target, Int32 with)
        {
            Int32 i, j = target;
            do
            {
                i = j;
                j = Interlocked.CompareExchange(ref target, i | with, i);
            } while (i != j);
            return j;
        }

        #endregion

        private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then)
        {
            return (Interlocked.CompareExchange(ref val, @then, @if) == @if);
        }

        private static Boolean IfThen(ref Int32 val, Int32 @if, Int32 then, out Int32 prevVal)
        {
            prevVal = Interlocked.CompareExchange(ref val, @then, @if);
            return (prevVal == @if);
        }

        ///


        /// 釋放資源
        ///

        public void Dispose()
        {
            if (m_WaiterLock != null)
            {
                m_WaiterLock.Close();
                m_WaiterLock = null;
            }
        }
    }
}
    

對于上面的這個代碼,我暈眩了好一段時間,不過當我真正理解的時候,從暈眩中學到了做多線程編程應該具備的思維方式。

首先從簡單的理解開始談,

1、原子化操作

對于InterLocked類,曾經也知道,但是卻用的很少,不過從該代碼中知道,在多線程的編程中對共享數據的寫入操作,一定要達到原子性。至于如何做到這點,InterlockedAnd和InterlockedOr做了很好的詮釋:

While循環的目的就是保證target值以***的值做與操作,如果傳入的值在執行的過程被其他線程改變的話,那么是不會退出該循環的,并會利用改變后的值重新做次與操作。

2、理解Enter和Exit

這兩個方法很難寫出來解釋,用圖是最清晰的。

曾經的暈眩:

1、Enter方法中為什么存在循環,為什么不是執行完waitone就結束,必須m_lockState等于c_IsFree的時候才結束?

線程的執行并不完全按照先前排好的順序去執行,有時會發生一些特殊的情況來使改變線程的調度順序,所以就可能會出現上圖灰色部分的情況,則為了解決該可能發生的問題(概率很小)循環機制就出現了。

2、為什么在WaitOne和Release之前,除了增加和減少等待者外,還需要判斷m_lockstate是否改變(進入Enter到執行Waitone前的這段時間)?

一般性的思維:

該程序的思維:

這樣做的好處就是盡量少的操作內核對象,提高性能!

多線程編程雖然復雜,但是我覺得很有意思和挑戰性,而且隨著硬件的發展,多線程編程會更加重要,既然已經上路就讓我們走到盡頭!

【編輯推薦】

  1. 白話詳解ASP.NET的設計思想
  2. 簡單理解ASP.NET MVC基本知識
  3. ASP.NET視頻教程
責任編輯:彭凡 來源: cnblogs
相關推薦

2011-06-13 10:03:19

Qt 多線程 編程

2011-07-08 16:43:46

iPhone Cocoa 多線程

2024-04-30 12:56:00

多線程.NET

2009-10-10 16:15:49

VB.NET開發多線程

2009-07-22 17:07:16

WPF插件開發.NET Framew

2009-10-12 13:32:58

VB.NET線程構造器

2009-07-28 15:30:34

ASP.NET多線程

2019-02-26 11:15:25

進程多線程多進程

2009-07-17 10:37:05

C#多線程

2011-08-31 16:22:51

LUA多線程

2011-08-08 13:50:29

iPhone開發 NSOperatio 多線程

2011-06-28 09:51:08

.NET對象相等

2012-11-12 09:26:06

.NET多線程

2009-07-29 09:38:06

Web開發ASP.NET

2009-07-21 17:09:47

ASP.NET多線程

2015-07-22 09:51:51

iOS開發線程

2015-07-22 09:39:38

IOS多線程同步

2010-01-21 15:10:37

VB.NET靜態托盤程

2009-10-19 11:28:42

VB.NET語言.NET開發語言

2009-03-24 08:56:23

數據同步多線程Java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产精品99久久久久久久久 | 中文字幕在线一区 | 久久69精品久久久久久久电影好 | 国产一二三视频在线观看 | 午夜一区二区三区在线观看 | 黄色片在线免费看 | 欧日韩不卡在线视频 | 亚洲一区二区在线播放 | 91久久久www播放日本观看 | 国产在线精品一区二区 | 国产成人精品一区二区三区网站观看 | 久久久久久久久久久久久久av | 免费视频成人国产精品网站 | 欧美视频一区二区三区 | 精品国产91乱码一区二区三区 | 欧美一区二区在线视频 | 正在播放国产精品 | 天天看天天摸天天操 | 免费看国产a | 噜噜噜噜狠狠狠7777视频 | 久久久精品一区 | 丁香婷婷综合激情五月色 | 亚洲天堂免费在线 | 欧美日韩国产一区二区三区 | 在线欧美a | 成人欧美在线 | 欧美精品一区二区三区在线播放 | 亚洲精品视频网站在线观看 | 精品亚洲一区二区三区四区五区高 | 精品欧美一区二区三区久久久 | 欧美激情综合五月色丁香小说 | 国产精品久久久久久久毛片 | 国产一区二区精品在线观看 | 欧美国产精品久久久 | 成人日批视频 | 久久九九网站 | 久久亚洲一区二区三区四区 | 亚洲精品一区在线观看 | 亚洲国产高清在线观看 | 天天天天操 | 四虎影音 |