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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发编程的目的和挑战

發(fā)布時間:2025/3/12 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程的目的和挑战 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

并發(fā)編程的目的與挑戰(zhàn)

并發(fā)編程的目的是為了讓程序運行得更快。啟動更多的線程并不一定就能讓程序最大限度地并發(fā)執(zhí)行。
希望通過多線程執(zhí)行任務(wù)讓程序運行得更快,會面臨非常多的挑戰(zhàn)。比如:

上下文切換的問題死鎖的問題硬件和軟件的資源限制問題

上下文切換

單核處理器也支持多線程執(zhí)行代碼,CPU通過給每個線程分配CPU時間片來實現(xiàn)這個機(jī)制。時間片是CPU分配給各個線程的時間,因為時間片非常短,所以CPU通過不停地切換線程執(zhí)行,讓我們感覺多個線程是同時執(zhí)行的,時間片一般是幾十毫秒(ms)。

CPU通過時間片分配算法來循環(huán)執(zhí)行任務(wù),當(dāng)前任務(wù)執(zhí)行一個時間片后會切換到下一個任務(wù)。但是,在切換前會保存上一個任務(wù)的狀態(tài),以便下次切換回這個任務(wù)時,可以再加載這個任務(wù)的狀態(tài)。所以任務(wù)從保存到再加載的過程就是一次上下文切換。

上下文切換也會影響多線程的執(zhí)行速度。

如何減少上下文切換

減少上下文切換的方法有 無鎖并發(fā)編程、CAS算法、使用最少線程 和 使用協(xié)程

無鎖并發(fā)編程。多線程競爭鎖時,會引起上下文切換,所以多線程處理數(shù)據(jù)時,可以用一些辦法來避免使用鎖,如將數(shù)據(jù)的ID按照Hash算法取模分段,不同的線程處理不同段的數(shù)據(jù)。

CAS算法。Java的Atomic包使用CAS算法來更新數(shù)據(jù),而不需要加鎖。

使用最少線程。避免創(chuàng)建不需要的線程,比如任務(wù)很少,但是創(chuàng)建了很多線程來處理,這樣會造成大量線程都處于等待狀態(tài)。

使用協(xié)程:在單線程里實現(xiàn)多任務(wù)的調(diào)度,并在單線程里維持多個任務(wù)間的切換。

死鎖

死鎖的簡述:就是倆個線程相互持有對方需要的資源,并且又同時等待對方釋放資源,導(dǎo)致倆個線程相互僵持,誰也不肯讓誰。

死鎖的定義:死鎖是指兩個或兩個以上的進(jìn)程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。

我們可以通過一個小故事理解死鎖。就是指有兩個人他們在一起吃飯,但是呢,筷子不夠,A這個人有一支筷子,B這個人也有一支筷子,假如A要吃飯的時候,B把筷子給了A,這樣A就吃上了飯,同理B要吃飯的時候,A把筷子給了B,這樣B也吃上了飯,如果要是這樣的話,就沒有我們什么事了,但是有一天,有一道菜非常好吃,A、B都想先吃,A向B拿筷子,B也先向A拿筷子。兩人都不愿意把筷子給對方,那只能一直耗著,等著,那么我們就可以說他們兩個死鎖了。

死鎖程序

那么如何使用java來編寫一個死鎖程序呢。簡單來說就是在同步代碼塊中嵌套同步代碼塊,兩個同步代碼塊應(yīng)用了兩個不同的鎖。A線程的第一個同步代碼塊用到了鎖A,第二個同步代碼塊用到了鎖B。B線程第一個同步代碼塊用到了鎖B,第二個同步代碼塊用到了鎖A。這樣當(dāng)A線程運行的時候先用了鎖A,還沒有用到鎖B的時候,B線程也啟動了,用到了鎖B,這時A線程要用鎖B,然而這時B線程卻已經(jīng)占用了鎖B,而B線程繼續(xù)運行需要鎖A,可是A線程已經(jīng)占用了鎖B,這樣話,這兩個線程就出現(xiàn)了死鎖。

示例

package com.zsh;/*** 死鎖:就是同步代碼塊中嵌套另外一個同步代碼塊* * @author 小行**/ public class DeadLockDemo {public static void main(String[] args) {// 創(chuàng)建兩個線程DeadLockThread dlt1 = new DeadLockThread(false);DeadLockThread dlt2 = new DeadLockThread(true);// 啟動線程new Thread(dlt1).start();new Thread(dlt2).start();} }class DeadLockThread implements Runnable {// 標(biāo)記變量private boolean flag;public DeadLockThread(boolean flag) {super();this.flag = flag;}public void run() {// dlt1線程執(zhí)行該方法if (flag) {synchronized (ThreadLock.locka) {System.out.println("if locka!");synchronized (ThreadLock.lockb) {System.out.println("if lockb!");}}} // dlt2線程執(zhí)行該方法else {synchronized (ThreadLock.lockb) {System.out.println("else lockb!");synchronized (ThreadLock.locka) {System.out.println("else locka!");}}}} }class ThreadLock {static Object locka = new Object();static Object lockb = new Object(); }

程序運行之后會出現(xiàn)死鎖的情況,希望大家可以通過這個例子深入理解死鎖。

避免死鎖的幾個常見方法

避免一個線程同時獲取多個鎖。

避免一個線程在鎖內(nèi)同時占用多個資源,盡量保證每個鎖只占用一個資源。

嘗試使用定時鎖,使用lock.tryLock(timeout)來替代使用內(nèi)部鎖機(jī)制。

對于數(shù)據(jù)庫鎖,加鎖和解鎖必須在一個數(shù)據(jù)庫連接里,否則會出現(xiàn)解鎖失敗的情況。

資源限制的挑戰(zhàn)

硬件資源限制有帶寬的上傳/下載速度、硬盤讀寫速度和CPU的處理速度。

軟件資源限制有數(shù)據(jù)庫的連接數(shù)和socket連接數(shù)等。

如何解決資源限制的問題

對于硬件資源限制,可以考慮使用集群并行執(zhí)行程序。比如使用ODPS、Hadoop或者自己搭建服務(wù)器集群。

對于軟件資源限制,可以考慮使用資源池將資源復(fù)用。比如使用連接池將數(shù)據(jù)庫和Socket連接復(fù)用,或者在調(diào)用對方webservice接口獲取數(shù)據(jù)時,只建立一個連接。

在資源限制情況下進(jìn)行并發(fā)編程

根據(jù)不同的資源限制調(diào)整程序的并發(fā)度,比如下載文件程序依賴于兩個資源——帶寬和硬盤讀寫速度。有數(shù)據(jù)庫操作時,涉及數(shù)據(jù)庫連接數(shù),如果SQL語句執(zhí)行非常快,而線程的數(shù)量比數(shù)據(jù)庫連接數(shù)大很多,則某些線程會被阻塞,等待數(shù)據(jù)庫連接。

了解更多關(guān)注我喲!!!

總結(jié)

以上是生活随笔為你收集整理的并发编程的目的和挑战的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。