中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中怎么利用多線程解決資源競爭

發布時間:2021-06-15 15:01:44 來源:億速云 閱讀:251 作者:Leah 欄目:編程語言

Java中怎么利用多線程解決資源競爭,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

一、c#下的幾種鎖的運用方式

1、臨界區,通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。

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

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

有這么個語法,不知道其實是以臨界區的方式處理資源競爭。

2、互斥量,為協調共同對一個共享資源的單獨訪問而設計的。

c#中有一個Mutex類,就在System.Threading命名空間下,Mutex其實就是互斥量,互斥量不單單能處理多線程之間的資源競爭,還能處理

進程之間的資源競爭,功能是比較強大的,但是開銷也很大,性能比較低。

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、信號量,為控制一個具有有限數量用戶資源而設計。

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、事 件:用來通知線程有一些事件已發生,從而啟動后繼任務的開始。

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、讀寫鎖,這種鎖允許在有其他程序正在寫的情況下讀取資源,所以如果資源允許臟讀,用這個比較合適

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、原子鎖,通過原子操作Interlocked.CompareExchange實現“無鎖”競爭

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、原子性操作,這是一種特例,野外原子性操作本身天生線程安全,所以無需加鎖

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

8、不加鎖,如果不加鎖,那多線程下運行結果肯定是錯的,這里貼上來比較一下性能

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

二、性能測試

1、測試代碼,執行1000,10000,100000,1000000次

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

   // 多線程
   Console.WriteLine();
   Console.WriteLine($"    線程數:{loopTimes}");
   Console.WriteLine($"   執行次數:{runTimes}");
   Console.WriteLine($"  校驗值應等于:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{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")}, 總耗時:{stopwatch.ElapsedMilliseconds}毫秒, 校驗值:{noLockInt}");
   Console.WriteLine();
  }

2、線程:10

Java中怎么利用多線程解決資源競爭

Java中怎么利用多線程解決資源競爭

Java中怎么利用多線程解決資源競爭

Java中怎么利用多線程解決資源競爭

3、線程:50

Java中怎么利用多線程解決資源競爭

Java中怎么利用多線程解決資源競爭

三、總結

Java中怎么利用多線程解決資源競爭

Java中怎么利用多線程解決資源競爭

1)在各種測試中,不加鎖肯定是最快的,所以盡量避免資源競爭導致加鎖運行

2)在多線程中Interlocked.CompareExchange始終表現出優越的性能,排在第二位

3)第三位lock,臨界區也表現出很好的性能,所以在別人說lock性能低的時候請反駁他

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

5)第五位讀寫鎖(ReaderWriterLockSlim)表現也還可以,并且支持無所讀,實用性還是比較好的

6)剩下的信號量、事件、互斥量,這三種性能最差,當然他們有各自的適用范圍,只是在處理資源競爭這方面表現不好

看完上述內容,你們掌握Java中怎么利用多線程解決資源競爭的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

额济纳旗| 禄丰县| 德钦县| 楚雄市| 米脂县| 手游| 蓝山县| 凤翔县| 马尔康县| 娄底市| 华安县| 英吉沙县| 奈曼旗| 林周县| 荆门市| 霍州市| 丰顺县| 东乌| 仪征市| 天气| 合江县| 八宿县| 旬阳县| 岢岚县| 临泽县| 河北省| 克山县| 永兴县| 龙南县| 定南县| 武鸣县| 仙桃市| 桐城市| 读书| 海晏县| 正定县| 库尔勒市| 景洪市| 沂南县| 南木林县| 新丰县|