《Java 高并發》01 高并發基本概念

基本概念

同步和異步

同步和異步通常是用來形容一次方法調用。

同步方法調用一旦開始,調用者必須等到方法返回才能繼續執行后續操作。

異步方法調用更像一個消息傳遞,一旦開始,方法調用就會立即返回,調用者就可以繼續后續的操作。異步方法通常會在另外一個線程中"真實"執行,整個過程不會影響調用者的工作。

舉例:到了飯點,我們點外賣,下單成功之后等待外賣小哥送餐。這就是同步調用。 不過,為了學習,我們在下單成功之后看了會《Java 從入門到放棄》書籍,邊等待外賣小哥送餐。這就是異步調用。

并發和并行

并發和并行兩個概念很容易被混淆。他們都可以表示兩個或者多個任務一起執行,但是偏重點有些不同。并發偏重于多個任務交替執行,而多個任務之間有可能還是串行的。而并行是真正意義上的"同時執行"。

?

嚴格來說,并行的多個任務是真實的同時執行,而對于并發來說,這個過程值是交替執行。一會兒執行A,一會兒執行B,系統會不停地在兩者間切換。但是對于外部觀察者來說,即使多個任務之間是串行并發的,也會造成多任務間是并行執行的錯覺。

舉例:三個人同時吃三個蘋果,這句是并行。而一個吃三個蘋果,這就是并發,他需要來回切換。

臨界區

臨界區用來表示一種公共資源或者說是共享數據,可以被多個線程使用。但是每一次,只能有一個線程使用它,一旦臨界區資源被占用,其他線程想要使用這個資源,則必須等待。

舉例:會議室開會,當有人正在使用會議室,而這個時候你又想要使用這個會議室,就必須等他們會議結束才能使用。

阻塞和非阻塞

阻塞和非阻塞通常是用來形容多線程間的相互影響。比如當臨界區資源被占用時,那么其他需要需要使用這個臨界區資源的線程就必須等待,等待會導致線程掛起,這種情況就是阻塞。非阻塞的意思與之相反,它強調沒有一個線程可以妨礙其他線程執行。

死鎖、饑餓、和活鎖

死鎖、饑餓和活鎖都屬于多線程的活躍性問題。

死鎖:多個進程對公共資源的相互競爭,導致循環等待的現象。比如:A->B->C->A,互相競爭,循環等待。

饑餓:指某一個線程或者多個線程因為某種原因無法獲得所需要的資源,導致一直無法執行。比如:線程優先級低,導致高優先級的線程不斷搶占它需要的資源,導致低優先級的線程無法工作。舉例:在自然界中,母鳥喂食。由于雛鳥很多,而食物有限,雛鳥之間的事務競爭可能非常厲害,小雛鳥因為經常搶不到食物,有可能會被餓死。

活鎖:活鎖恰恰與死鎖相反,死鎖是大家都拿不到資源都占用著對方的資源,而活鎖是拿到資源卻又相互釋放不執行。當多線程中出現了相互謙讓,都主動將資源釋放給別的線程使用,這樣這個資源在多個線程之間跳動而又得不到執行,這就是活鎖。舉例:兩個人迎面走來時,有時候因為有事比較急,而為了快速通過會避讓對方先行。恰好對方也為了能快速通過禮讓你先行,結果撞上了。于是乎,都意識到了這個問題,希望盡快避讓對方,你向右他向左,結果又撞上了。

并發級別

由于臨界區的存在,多線程之間的并發必須收到控制。根據控制并發的策略對并發的級別進行分類,大致為阻塞無饑餓無障礙無鎖無等待

阻塞

一個線程是阻塞的,那么在其他線程釋放資源之前,當前線程無法繼續執行。當使用 Synchronized 關鍵字或者重入鎖時,我們得到的就是阻塞線程。

無饑餓

如果線程之間是有優先級的,那么線程調度的時候總是會傾向于滿足高優先級的線程。也就是說,對于同一個資源的分配,是不公平的。那就出現了公平和非公平兩種情況。對于非公平鎖來說,系統允許優先級高的線程插隊。這樣有可能導致優先級低的線程產生饑餓。但如果鎖是公平的,滿足先來后到,那么接就不會產生,不論新來的線程優先級高低,想要獲得資源就必須乖乖排隊,那么所有的線程都有機會執行。

無障礙

無障礙是一種最弱的非阻塞調度。兩個線程如果是無障礙的執行,那么他們不會因為臨界區的問題導致一方被掛起。換言之,大家都可以大搖大擺地進入臨界區了。對于無障礙的線程來說,一旦檢測到數據被修改壞了,它會立即對自己所做的修改進行回滾,確保數據的安全。

如果說阻塞的控制方式是悲觀策略,那么非阻塞的調度就是一種樂觀的策略。它任務多個線程之間很有可能不會發生沖突,或者說這種概率不大。因此大家都應該無障礙的執行,但是一旦檢測到沖突,就應該進行回滾。但是無障礙的多線程程序并不一定能夠順暢的運行,因為當臨界區中存在嚴重的沖突時,所有的線程可能都會不斷地回滾自己的操作,而沒有一個線程可以走出臨界區。這種情況會影響系統的正常執行。所有,我們希望在這一堆線程中,至少有一個線程能夠在有效的時間內完成自己的操作,從而退出臨界區。至少這樣可以保證系統不會在臨界區中進行無線的等待。

一種可行的無障礙實現可以依賴一個"一致性標記"來實現。線程在操作之前,線程讀取并保存這個標記,在操作完成后,在此讀取,檢查這個標記是否被更改過,如果兩者是一致的,則的說明資源訪問沒有沖突。如果不一致,則說明資源可能在操作過程中與其他線程沖突,需要重試操作。

無鎖

無鎖的并行都是無障礙的。在無鎖的情況下,所有的線程都能嘗試對臨界區進行訪問,但是不同的是,無鎖的并發保證必然有一個線程能夠在有限步內完成操作離開臨界區。

無等待

無鎖只要求有一個線程可以在有限步內完成操作,而無等待則是在無鎖的基礎上更進一步進行擴展。它要求所有的線程都必須在有限步內完成,這樣就不會引起饑餓問題。如果限制這個步驟上限,還可以進一步分解為有界無等待和線程數無關的無等待幾種,他們之間的區別只是對循環次數的限制不同。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/273552.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/273552.shtml
英文地址,請注明出處:http://en.pswp.cn/news/273552.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android之Http網絡編程(四)

前面幾篇博文簡單的介紹了一些常見的Http的操作,這些操作幾乎都是在新開的線程中進行的網絡請求,并在日志中打印出獲取到的網絡數據。那么,問題來了!(呃~感覺下一句是藍翔有木有?)如何在把獲取到…

《Java 高并發》02 多線程的特性

多線程的三大特性:原子性、可見性和有序性。 原子性 原子性是指一個操作或者多個操作,一旦開始就不會被其他線程干擾,即使是在多個線程一起執行的情況下也不會被干擾。或者不執行。 原子性主要是為了保證數據一致,線程安全問題…

U3D-FSM有限狀態機的簡單設計

http://coder.beitown.com/archives/592 在之前的文章里介紹了一個基礎U3D狀態機框架(Unity3D游戲開發之狀態流框架)即大Switch的枚舉狀態控制。這種方法雖然容易理解,編程方法也相對簡單,但是弊端是當狀態變得復雜之后&#xff0…

《Java 高并發》04 線程的基本操作

新建線程 新建線程很簡單。只要使用new 關鍵字創建一個線程對象,并且調用 start 方法啟動線程。 Thread t new Thread(); t.start();注意:run 方法不是用來啟動線程。如果調用 run 方法它只會作為普通方法來執行,而不會開啟線程執行。 終止…

Dispatch 方法簡介

后臺執行 dispatch_async(dispatch_get_global_queue(0, 0), ^{ //后臺程執行 something; }); 主線程執行 dispatch_async(dispatch_get_main_queue(), ^{// 主線程執行something; }); 一次性執行 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 主…

linux雜七雜八整理

64系統里執行32位程序: 1、在64系統里執行32位程序如果出現/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory,安裝下glic即可sudo yum install glibc.i6862、error while loading shared libraries: libz.so.1: cannot …

《Java 高并發》05 線程的基本操作

volatile 與 Java 內存模型 Java 內存模型都是圍繞著原子性、有序性和可見性展開的。為了在適當的場合,確保線程間的原子性、有序性和可見性。Java 使用了一些特許的操作或者關鍵字來申明、告訴虛擬機,在這個地方,要尤其注意,不能…

mybatis 2 -常用數據操作

1、寫入數據并獲取自增ID XML配置&#xff1a; <!-- 寫入數據獲取自增ID --><insert id"insertLog" parameterType"com.mamaguwen.entity.sys_loginlog" useGeneratedKeys"true" keyProperty"logid">insert into sys_…

Spring常用的的注解對應xml配置詳解

Component(value"")注解&#xff1a;組件 標記在類上&#xff0c;也可以放在接口上注解作用&#xff1a;把AccountDao實現類對象交由Spring IOC容器管理 相當于XML配置文件中的Bean標簽 <bean id"userAnnonMapper" class"com.spring.mapper.User…

安卓模擬器bluestacks mac地址修改教程

http://szmars2008.blog.163.com/blog/static/118893702201373181349348/ 轉載于:https://www.cnblogs.com/prayer521/p/4069037.html

Docker 搭建 ELK 日志系統,并通過 Kibana 查看日志

Docker 搭建 ELK 日志系統,并通過 Kibana 查看日志 docker-compose.yml version: 3 services:elasticsearch:image: elasticsearch:7.7.0 #鏡像container_name: elasticsearch #定義容器名稱restart: always #開機啟動&#xff0c;失敗也會一直重啟environment:- "cl…

蟠桃記

Problem Description 喜歡西游記的同學肯定都知道悟空偷吃蟠桃的故事&#xff0c;你們一定都覺得這猴子太鬧騰了&#xff0c;其實你們是有所不知&#xff1a;悟空是在研究一個數學問題&#xff01; 什么問題&#xff1f;他研究的問題是蟠桃一共有多少個&#xff01; 不過&#…

Spring 定時任務動態管理

管理 Spring 中定時任務 pom.xml <properties><hutool.version>5.6.6</hutool.version><lombok.version>1.18.20</lombok.version><spring-boot.web.version>2.2.10.RELEASE</spring-boot.web.version> </properties><de…

高效率Oracle SQL語句

1、Where子句中的連接順序&#xff1a; ORACLE采用自下而上的順序解析WHERE子句。 根據這個原理&#xff0c;表之間的連接必須寫在其他WHERE條件之前&#xff0c; 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。 舉例&#xff1a; (低效) select ... from table1…

RabbitMQ Management:Management API returned status code 500

錯誤顯示&#xff1a; 解決方案&#xff1a; 因為是使用docker 容器安裝的&#xff0c;所有需要進入容器 docker exec -it rabbitmq /bin/bash進入目錄 cd /etc/rabbitmq/conf.d/執行命令 echo management_agent.disable_metrics_collector false > management_agent.dis…

Android JNI和NDK學習(5)--JNI分析API

Java類型和本地類型對應 在如下情況下&#xff0c;需要在本地方法中應用java對象的引用&#xff0c;就會用到類型之間的轉換&#xff1a; java方法里面將參數傳入本地方法&#xff1b;在本地方法里面創建java對象&#xff1b;在本地方法里面return結果給java程序。Java基本類型…

RabbitMq 消費失敗,重試機制

方案一&#xff1a; 本地消息表 定時任務 本地消息表&#xff1a;主要用于存儲 業務數據、交換機、隊列、路由、次數 定時任務&#xff1a;定時掃描本地消息表&#xff0c;重新給業務隊列投遞消息。 具體思路&#xff1a;業務隊列消費失敗時&#xff0c;把 業務數據、交換機、…

Android常用的工具類

主要介紹總結的Android開發中常用的工具類&#xff0c;大部分同樣適用于Java。目前包括HttpUtils、DownloadManagerPro、ShellUtils、PackageUtils、 PreferencesUtils、JSONUtils、FileUtils、ResourceUtils、StringUtils、 ParcelUtils、RandomUtils、ArrayUtils、ImageUtils…

0. Spring 基礎

BeanDefinition BeanDefinition 表示 Bean 定義&#xff1a; Spring根據BeanDefinition來創建Bean對象&#xff1b;BeanDefinition有很多的屬性用來描述Bean&#xff1b;BeanDefiniton是Spring中非常核心的概念。BeanDefiniton中重要的屬性&#xff1a; a. beanClass&#xf…

1. Spring 源碼:Spring 解析XML 配置文件,獲得 Bena 的定義信息

通過 Debug 運行 XmlBeanDefinitionReaderTests 類的 withFreshInputStream() 的方法&#xff0c;調試 Spring 解析 XML 配置文件&#xff0c;獲得 Bean 的定義。 大體流程可根據序號查看&#xff0c;xml 配置文件隨便看一眼&#xff0c;不用過多在意。 <?xml version&qu…