最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程下解決資源競(jìng)爭(zhēng)的7種方法詳解

 更新時(shí)間:2019年08月14日 08:51:33   作者:藍(lán)建榮  
這篇文章主要介紹了Java多線程下解決資源競(jìng)爭(zhēng)的7種方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

前言

一般情況下,只要涉及到多線程編程,程序的復(fù)雜性就會(huì)顯著上升,性能顯著下降,BUG出現(xiàn)的概率大大提升。

多線程編程本意是將一段程序并行運(yùn)行,提升數(shù)據(jù)處理能力,但是由于大部分情況下都涉及到共有資源的競(jìng)爭(zhēng),所以修改資源

對(duì)象時(shí)必須加鎖處理。但是鎖的實(shí)現(xiàn)有很多種方法,下面就來(lái)一起了解一下在C#語(yǔ)言中幾種鎖的實(shí)現(xiàn)與其性能表現(xiàn)。

一、c#下的幾種鎖的運(yùn)用方式

1、臨界區(qū),通過(guò)對(duì)多線程的串行化來(lái)訪問(wèn)公共資源或一段代碼,速度快,適合控制數(shù)據(jù)訪問(wèn)。

private static object obj = new object();
  private static int lockInt;
  private static void LockIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    lock (obj)
    {
     lockInt++;
    }
   }
  }

你沒(méi)看錯(cuò),c#中的lock語(yǔ)法就是臨界區(qū)(Monitor)的一個(gè)語(yǔ)法糖,這大概是90%以上的.net程序員首先想到的鎖,不過(guò)大部分人都只是知道

有這么個(gè)語(yǔ)法,不知道其實(shí)是以臨界區(qū)的方式處理資源競(jìng)爭(zhēng)。

2、互斥量,為協(xié)調(diào)共同對(duì)一個(gè)共享資源的單獨(dú)訪問(wèn)而設(shè)計(jì)的。

c#中有一個(gè)Mutex類,就在System.Threading命名空間下,Mutex其實(shí)就是互斥量,互斥量不單單能處理多線程之間的資源競(jìng)爭(zhēng),還能處理

進(jìn)程之間的資源競(jìng)爭(zhēng),功能是比較強(qiáng)大的,但是開(kāi)銷也很大,性能比較低。

private static Mutex mutex = new Mutex();
  private static int mutexInt;
  private static void MutexIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    mutex.WaitOne();
    mutexInt++;
    mutex.ReleaseMutex();
   }
  }

3、信號(hào)量,為控制一個(gè)具有有限數(shù)量用戶資源而設(shè)計(jì)。

private static Semaphore sema = new Semaphore(1, 1);
  private static int semaphoreInt;
  private static void SemaphoreIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    sema.WaitOne();
    semaphoreInt++;
    sema.Release();
   }
  }

4、事 件:用來(lái)通知線程有一些事件已發(fā)生,從而啟動(dòng)后繼任務(wù)的開(kāi)始。

public static AutoResetEvent autoResetEvent = new AutoResetEvent(true);
  private static int autoResetEventInt;
  private static void AutoResetEventIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    if (autoResetEvent.WaitOne())
    {
     autoResetEventInt++;
     autoResetEvent.Set();
    }
   }
  }

5、讀寫(xiě)鎖,這種鎖允許在有其他程序正在寫(xiě)的情況下讀取資源,所以如果資源允許臟讀,用這個(gè)比較合適

private static ReaderWriterLockSlim LockSlim = new ReaderWriterLockSlim();
  private static int lockSlimInt;
  private static void LockSlimIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    LockSlim.EnterWriteLock();
    lockSlimInt++;
    LockSlim.ExitWriteLock();
   }
  }

6、原子鎖,通過(guò)原子操作Interlocked.CompareExchange實(shí)現(xiàn)“無(wú)鎖”競(jìng)爭(zhēng)

private static int isLock;
  private static int ceInt;
  private static void CEIntAdd()
  {
   //long tmp = 0;
   for (var i = 0; i < runTimes; i++)
   {
    while (Interlocked.CompareExchange(ref isLock, 1, 0) == 1) { Thread.Sleep(1); }

    ceInt++;
    Interlocked.Exchange(ref isLock, 0);
   }
  }

7、原子性操作,這是一種特例,野外原子性操作本身天生線程安全,所以無(wú)需加鎖

private static int atomicInt;
  private static void AtomicIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    Interlocked.Increment(ref atomicInt);
   }
  }

8、不加鎖,如果不加鎖,那多線程下運(yùn)行結(jié)果肯定是錯(cuò)的,這里貼上來(lái)比較一下性能

private static int noLockInt;
  private static void NoLockIntAdd()
  {
   for (var i = 0; i < runTimes; i++)
   {
    noLockInt++;
   }
  }

二、性能測(cè)試

1、測(cè)試代碼,執(zhí)行1000,10000,100000,1000000次

private static void Run()
  {
   var stopwatch = new Stopwatch();
   var taskList = new Task[loopTimes];

   // 多線程
   Console.WriteLine();
   Console.WriteLine($"    線程數(shù):{loopTimes}");
   Console.WriteLine($"   執(zhí)行次數(shù):{runTimes}");
   Console.WriteLine($"  校驗(yàn)值應(yīng)等于:{runTimes * loopTimes}");

   // AtomicIntAdd
   stopwatch.Restart();
   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { AtomicIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("AtomicIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{atomicInt}");

   // CEIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { CEIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("CEIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{ceInt}");

   // LockIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { LockIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("LockIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{lockInt}");

   // MutexIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { MutexIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("MutexIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{mutexInt}");

   // LockSlimIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { LockSlimIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("LockSlimIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{lockSlimInt}");

   // SemaphoreIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { SemaphoreIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("SemaphoreIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{semaphoreInt}");


   // AutoResetEventIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { AutoResetEventIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("AutoResetEventIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{autoResetEventInt}");

   // NoLockIntAdd
   taskList = new Task[loopTimes];
   stopwatch.Restart();

   for (var i = 0; i < loopTimes; i++)
   {
    taskList[i] = Task.Factory.StartNew(() => { NoLockIntAdd(); });
   }
   Task.WaitAll(taskList);
   Console.WriteLine($"{GetFormat("NoLockIntAdd")}, 總耗時(shí):{stopwatch.ElapsedMilliseconds}毫秒, 校驗(yàn)值:{noLockInt}");
   Console.WriteLine();
  }


2、線程:10

3、線程:50

三、總結(jié)

1)在各種測(cè)試中,不加鎖肯定是最快的,所以盡量避免資源競(jìng)爭(zhēng)導(dǎo)致加鎖運(yùn)行

2)在多線程中Interlocked.CompareExchange始終表現(xiàn)出優(yōu)越的性能,排在第二位

3)第三位lock,臨界區(qū)也表現(xiàn)出很好的性能,所以在別人說(shuō)lock性能低的時(shí)候請(qǐng)反駁他

4)第四位是原子性變量(Atomic)操作,不過(guò)目前只支持變量的自增自減,適用性不強(qiáng)

5)第五位讀寫(xiě)鎖(ReaderWriterLockSlim)表現(xiàn)也還可以,并且支持無(wú)所讀,實(shí)用性還是比較好的

6)剩下的信號(hào)量、事件、互斥量,這三種性能最差,當(dāng)然他們有各自的適用范圍,只是在處理資源競(jìng)爭(zhēng)這方面表現(xiàn)不好

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

宝坻区| 新龙县| 石柱| 靖安县| 寿阳县| 巴彦县| 曲阳县| 琼海市| 鱼台县| 宁武县| 西乌珠穆沁旗| 塔城市| 抚宁县| 阿拉善右旗| 汪清县| 通化市| 江源县| 凌海市| 井陉县| 西城区| 应用必备| 赤峰市| 和田县| 南宁市| 政和县| 芮城县| 盐边县| 元谋县| 南宁市| 浦城县| 乐都县| 东山县| 共和县| 柘荣县| 保定市| 自贡市| 调兵山市| 衡阳县| 甘孜| 梨树县| 邹平县|