程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 線程系列07,使用lock語句塊或Interlocked類型方法保證自增變量的數據同步,lockinterlocked

線程系列07,使用lock語句塊或Interlocked類型方法保證自增變量的數據同步,lockinterlocked

編輯:C#入門知識

線程系列07,使用lock語句塊或Interlocked類型方法保證自增變量的數據同步,lockinterlocked


假設多個線程共享一個靜態變量,如果讓每個線程都執行相同的方法每次讓靜態變量自增1,這樣的做法線程安全嗎?能保證自增變量數據同步嗎?本篇體驗使用lock語句塊和Interlocked類型方法保證自增變量的數據同步。

 

□ 線程不安全、數據不同步的做法

 

    class Program
    {
        static int sum = 0;
        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            Parallel.For(0, Environment.ProcessorCount, i =>
            {
                for (int j = 0; j < 100000000; ++j)
                {
                    AddOne();
                }
            });
            watch.Stop();
            Console.WriteLine("sum={0},用了{1}", sum, watch.Elapsed);
            Console.ReadKey();
        }
        static void AddOne()
        {
            sum++;
        }
    }

○ 變量sum是靜態的,供所有線程共享
○ Parallel.For提供並行循環, Environment.ProcessorCount表示處理器的處理,如果有4個CPU,就做4組循環

我們發現,結果不是我們期望的400000000,也就是說,在這種情況下的靜態變量自增不是線程安全的,換句話說,無法保證共享數據的同步。

 

□ 通過lock語句塊保持數據同步

 

lock語句塊能保證在同一時間只有一個線程進入其中。
    class Program
    {
        static int sum = 0;
        private static readonly object o = new object();
        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            Parallel.For(0, Environment.ProcessorCount, i =>
            {
                for (int j = 0; j < 100000000; ++j)
                {
                    AddOne();
                }
            });
            watch.Stop();
            Console.WriteLine("sum={0},用了{1}", sum, watch.Elapsed);
            Console.ReadKey();
        }
        static void AddOne()
        {
            lock (o)
            {
                sum++;
            }
            
        }
    }

這一次,使用lock語句塊得到了預期的結果。

 

□ 使用Interlocked保持數據同步

對於int或long類型變量的自增,並且保證類型安全,可以使用Interlocked類。提供的方法包括:

 

○ int Interlocked.Increment(ref int location),自增1
○ long Interlocked.Increment(ref long location),自增1
○ int Interlocked.Decrement(ref int location),自減1
○ long Interlocked.Decrement(ref long location),自減1
○ int Interlocked.Add(ref int location, int value),自增一個值
○ long Interlocked.Add(ref long location, long value),自增一個值

 

    class Program
    {
        static int sum = 0;
        static void Main(string[] args)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            Parallel.For(0, Environment.ProcessorCount, i =>
            {
                for (int j = 0; j < 100000000; ++j)
                {
                    AddOne();
                }
            });
            watch.Stop();
            Console.WriteLine("sum={0},用了{1}", sum, watch.Elapsed);
            Console.ReadKey();
        }
        static void AddOne()
        {
            Interlocked.Increment(ref sum);
        }
    }


使用Interlocked也能保證線程安全、數據同步,但耗時較長。


總結:
○ lock語句塊和Interlocked類型方法都能保證自增變量的線程安全、數據同步
○ Interlocked類型方法只適用於int,long類型變量,有一定的局限性

 

線程系列包括:

線程系列01,前台線程,後台線程,線程同步

線程系列02,多個線程同時處理一個耗時較長的任務以節省時間

線程系列03,多線程共享數據,多線程不共享數據

線程系列04,傳遞數據給線程,線程命名,線程異常處理,線程池

線程系列05,手動結束線程

線程系列06,通過CLR代碼查看線程池及其線程

線程系列07,使用lock語句塊或Interlocked類型方法保證自增變量的數據同步


c# 題目 2道 多線程 xml SQL 1道

補充回復:
select
現金支付數量=(select count(*) as from test where type=1),
現金支付金額=(select sum(*) from test where type=1
),
銀行支付數量=(select count(*) from test where type=2
)
,銀行支付金額=(select count(*) from test where type=2
)

1,多線程有哪幾種方法

1。當一個線程進入moniter(也就是說站用一個object),另一個線程只有等待或返回,而我們把返回就稱為一種模式,這種模式的英文是Balking。

2。這兩個線程可以是有序的執行,而不是讓OS來調度,這時我們要用一個object來調度,這種模式稱為Scheduler。(這個詞及其含義其實OS中就有)。

3。如果這兩個線程同時讀一個資源,我們可以讓他們執行,但如果同時寫的話,你閉著眼睛都會知道可能出現問題,這時我們就要用另一種模式(Read/Write Lock)。

4。如果一個線程是為另一個線程服務的話,比如IE中負責數據傳輸的線程和界面顯示的線程,當一個圖片沒有傳完時,另一個線程就無法顯示,至少是部分沒有傳完。那麼這時我們要用一個模式稱為生產者和消費者,英文是Producer-Consumer。

5。兩個線程的消亡也可以不是完全又OS來控制的,這時我們需要給出一個條件,使得每個線程在符合條件是才消亡,也就是有序的消亡,我們稱為Two-Phase Termination。

同步有哪幾種方法
一、volatile關鍵字

volatile是最簡單的一種同步方法,當然簡單是要付出代價的。它只能在變量一級做同步,volatile的含義就是告訴處理器, 不要將我放入工作內存, 請直接在主存操作我。(【轉自 】)因此,當多線程同時訪問該變量時,都將直接操作主存,從本質上做到了變量共享。

二、lock關鍵字

lock是一種比較好用的簡單的線程同步方式,它是通過為給定對象獲取互斥鎖來實現同步的。它可以保證當一個線程在關鍵代碼段的時候,另一個線程不會進來,它只能等待,等到那個線程對象被釋放,也就是說線程出了臨界區。用法:

三、System.Threading.Interlocked

對於整數數據類型的簡單操作,可以用 Interlocked 類的成員來實現線程同步,存在於System.Threading命名空間。Interlocked類有以下方法:Increment , Decrement , Exchange 和CompareExchange 。使用Increment 和Decrement 可以保證對一個整數的加減為一個原子操作。Exchange 方法自動交換指定變量的值。CompareExchange 方法組合了兩個操作:比較兩個值以及根據比較的結果將第三個值存儲在其中一個變量中。比較和交換操作也是按原子操作執行的。如:

2,xml有哪幾種訪問方式

這道題你去搜吧 我很討厭這類問題 有幾種訪問方式?知道怎麼去讀,怎麼最優化地去讀就好了 要知道那麼多訪問方式干嘛呢。。

3,SQL,表test:

現金支付數量
select count(*) from test where type=1
現金支付金額
select sum(*) from test where type=1
銀行支付數量
select count(*) from test where type=......余下全文>>
 

java線程同步問題(synchronized)

在java中除了8中基本數據類型,其余的參數傳遞全部是引用傳遞
你只定義一了lock,當然四個線程都是使用了同一個lock
因此lock可以當做"鎖"來使用
每個線程執行到synchronized (lock)時,都會去申請lock的鎖(每個對象都有一個唯一的鎖)
申請到了才能執行synchronized 語句塊裡的內容,執行完了會釋放lock的鎖
沒有申請到鎖的線程會等待(lock有一個等待隊列),處於阻塞狀態,當有線程用完了鎖就會喚醒一個在等待lock鎖的一個線程...
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved