日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发编程问题

發布時間:2024/3/24 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

并發編程的目的是為了讓程序運行得更快,但是,并不是啟動更多的線程就能讓程序最大限度地并發執行。在進行并發編程時,如果希望通過多線程執行任務讓程序運行得更快,會面臨非常多的挑戰,比如上下文切換的問題、死鎖的問題,以及受限于硬件和軟件的資源限制 問題,本章會介紹幾種并發編程的挑戰以及解決方案。

上下文切換

CPU通過時間片分配算法來循環執行任務,當前任務執行一個時間片后會切換到下一個 任務。但是,在切換前會保存上一個任務的狀態,以便下次切換回這個任務時,可以再加載這個任務的狀態。所以任務從保存到再加載的過程就是一次上下文切換。

多線程一定快嗎

當并發執行累加操作不超過百萬次時,速度會比串行執行累加操作要慢。那么,為什么并發執行的速度會比串行慢呢?這是因為線程有創建和上下文切換的開銷。

測試上下文切換次數和時長

下面我們來看看有什么工具可以度量上下文切換帶來的消耗。

使用Lmbench3是一個性能分析工具,可以測量上下文切換的時長。
使用vmstat可以測量上下文切換的次數。

如何減少上下文切換

減少上下文切換的方法有無鎖并發編程、CAS算法、使用最少線程和使用協程。

無鎖并發編程。多線程競爭鎖時,會引起上下文切換,所以多線程處理數據時,可以用一些辦法來避免使用鎖,如將數據的ID按照Hash算法取模分段,不同的線程處理不同段的數據。
CAS算法。Java的Atomic包使用CAS算法來更新數據,而不需要加鎖。
使用最少線程。避免創建不需要的線程,比如任務很少,但是創建了很多線程來處理,這 樣會造成大量線程都處于等待狀態。
協程:在單線程里實現多任務的調度,并在單線程里維持多個任務間的切換。

減少上下文切換

查看線程狀態,看是否有機會來減少上下文切換次數。
第一步:用jstack命令dump線程信息,看看某一進程里的線程都在做什么。

jstack pid > /home/develop/dump

第二步:統計所有線程分別處于什么狀態。

grep java.lang.Thread.State dump17 | awk ‘{print $2$3$4$5}’ | sort |uniq -c

如果處于空閑的線程過多,可以合理降低線程數量。因為每一次從 WAITTING到RUNNABLE都會進行一次上下文的切換。讀者也可以使用vmstat命令測試一下。

死鎖

產生條件

互斥條件:進程要求對所分配的資源進行排它性控制,即在一段時間內某資源僅為一進程所占用。
請求和保持條件:當進程因請求資源而阻塞時,對已獲得的資源保持不放。
不剝奪條件:進程已獲得的資源在未使用完之前,不能剝奪,只能在使用完時由自己釋放。
環路等待條件:在發生死鎖時,必然存在一個進程–資源的環形鏈。

避免死鎖的幾個常見方法。

避免一個線程同時獲取多個鎖。
避免一個線程在鎖內同時占用多個資源,盡量保證每個鎖只占用一個資源。
嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用內部鎖機制。
對于數據庫鎖,加鎖和解鎖必須在一個數據庫連接里,否則會出現解鎖失敗的情況。

資源限制的挑戰

什么是資源限制

資源限制是指在進行并發編程時,程序的執行速度受限于計算機硬件資源或軟件資源。

資源限制引發的問題

在并發編程中,將代碼執行速度加快的原則是將代碼中串行執行的部分變成并發執行,
但是如果將某段串行的代碼并發執行,因為受限于資源,仍然在串行執行,這時候程序不僅不
會加快執行,反而會更慢,因為增加了上下文切換和資源調度的時間。

如何解決資源限制的問題

對于硬件資源限制,可以考慮使用集群并行執行程序。既然單機的資源有限制,那么就讓
程序在多機上運行。比如使用ODPS、Hadoop或者自己搭建服務器集群,不同的機器處理不同
的數據。可以通過“數據ID%機器數”,計算得到一個機器編號,然后由對應編號的機器處理這 筆數據。
對于軟件資源限制,可以考慮使用資源池將資源復用。比如使用連接池將數據庫和Socket
連接復用,或者在調用對方webservice接口獲取數據時,只建立一個連接。

在資源限制情況下進行并發編程

如何在資源限制的情況下,讓程序執行得更快呢?方法就是,根據不同的資源限制調整
程序的并發度,比如下載文件程序依賴于兩個資源——帶寬和硬盤讀寫速度。有數據庫操作
時,涉及數據庫連接數,如果SQL語句執行非常快,而線程的數量比數據庫連接數大很多,則某些線程會被阻塞,等待數據庫連接。

小結
java提供的juc工具類已經可以充分解決以上出現的幾個問題。

本章知識點如下:

什么是下文切換
多線程一定快嗎
如何測試上下文切換次數和時長
如何減少上下文切換
死鎖如何產生
如何避免死鎖
什么是資源限制
如何解決資源限制的問題

附源碼1單線程與多線程性能對比:

public class ConcurrencyTest {private static final long count = 10000l;public static void main(String[] args) throws InterruptedException {concurrency();serial();}private static void concurrency() throws InterruptedException {long start = System.currentTimeMillis();Thread thread = new Thread(new Runnable() {@Overridepublic void run() {int a = 0;for (long i = 0; i < count; i++) {a += 5;}}});thread.start();int b = 0;for (long i = 0; i < count; i++) {b--;}long time = System.currentTimeMillis() - start;thread.join();System.out.println("concurrency :" + time + "ms,b=" + b);}private static void serial() {long start = System.currentTimeMillis();int a = 0;for (long i = 0; i < count; i++) {a += 5;}int b = 0;for (long i = 0; i < count; i++) {b--;}long time = System.currentTimeMillis() - start;System.out.println("serial:" + time + "ms,b=" + b + ",a=" + a);} }

附源碼2 死鎖:

public class DeadLockDemo {private static String A = "A";private static String B = "B";public static void main(String[] args) {new DeadLockDemo().deadLock();}private void deadLock() {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (A) {try {Thread.currentThread().sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (B) {System.out.println("1");}}}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (B) {synchronized (A) {System.out.println("2");}}}});t1.start();t2.start();} }

總結

以上是生活随笔為你收集整理的并发编程问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。