上下文切換的確切含義瞭解下

上下文切換的含義

其實在單個處理器的時期,操作系統就能處理多線程併發任務。處理器給每個線程分配 CPU 時間片(Time Slice),線程在分配獲得的時間片內執行任務。

CPU 時間片是 CPU 分配給每個線程執行的時間段,一般爲幾十毫秒。在這麼短的時間內線程互相切換,我們根本感覺不到,所以看上去就好像是同時進行的一樣。

時間片決定了一個線程可以連續佔用處理器運行的時長。當一個線程的時間片用完了,或者因自身原因被迫暫停運行了,這個時候,另外一個線程(可以是同一個線程或者其它進程的線程)就會被操作系統選中,來佔用處理器。這種一個線程被暫停剝奪使用權,另外一個線程被選中開始或者繼續運行的過程就叫做上下文切換(Context Switch)。

具體來說,一個線程被剝奪處理器的使用權而被暫停運行,就是“切出”;一個線程被選中佔用處理器開始或者繼續運行,就是“切入”。在這種切出切入的過程中,操作系統需要保存和恢復相應的進度信息,這個進度信息就是“上下文”了。

那上下文都包括哪些內容呢?具體來說,它包括了寄存器的存儲內容以及程序計數器存儲的指令內容。CPU 寄存器負責存儲已經、正在和將要執行的任務,程序計數器負責存儲 CPU 正在執行的指令位置以及即將執行的下一條指令的位置。

在當前 CPU 數量遠遠不止一個的情況下,操作系統將 CPU 輪流分配給線程任務,此時的上下文切換就變得更加頻繁了,並且存在跨 CPU 上下文切換,比起單核上下文切換,跨核切換更加昂貴。

什麼原因會導致上下文切換

在操作系統中,上下文切換的類型還可以分爲進程間的上下文切換和線程間的上下文切換。而在多線程編程中,我們主要面對的就是線程間的上下文切換導致的性能問題,下面我們就重點看看究竟是什麼原因導致了多線程的上下文切換。開始之前,先看下系統線程的生命週期狀態。

結合圖示可知,線程主要有 NEW、RUNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINADTED 等 6 種狀態。

在這個運行過程中,線程由 RUNNABLE 轉爲非 RUNNABLE 的過程就是線程上下文切換。拋開新建和死亡狀態,從上面的圖中可以看出:上下文切換主要發生在RUNABLE狀態和BLOCKED、WAITING、TIMED_WAITING這些狀態的互相轉換之間。

舉個列子,一個線程的狀態由 RUNNING 轉爲 BLOCKED ,再由 BLOCKED 轉爲 RUNNABLE ,然後再被調度器選中執行,這就是一個上下文切換的過程。

通過線程的運行狀態以及狀態間的相互切換,我們可以瞭解到,多線程的上下文切換實際上就是由多線程兩個運行狀態的互相切換導致的

根據上面的分析,我們可以總結出導致上下文切換的幾個原因:

  • CPU時間片用完,導致正常的上下文切換;
  • sleep()、wait()、yield()、join()、park()、synchronized、lock這些方法或者關鍵字會導致線程狀態的轉換,所以這些方法的調用也會導致上下文的切換;(需要注意的是這些方法的調用雖然後導致上下文切換,但是並不會佔用CPU資源,也就是說並不會提升CPU使用率);
  • 另外,JVM虛擬機在進行垃圾回收時,會進行STOP-THE-WORLD,這個操作會暫停所有Java線程,垃圾收集完之後線程再進入工作狀態,其實這個也是一種上下文切換操作。

怎麼查看系統上下文切換的數據

分線程的狀態

第一步:用jstack命令dump線程信息,看看pid爲3117的進程裏的線程都在做什麼。sudo -u admin /opt/ifeve/java/bin/jstack 31177 >/home/tengfei.fangtf/dump17

第二步:統計所有線程分別處於什麼狀態,發現300多個線程處於WAITING(onobject-monitor)狀態。

[tengfei.fangtf@ifeve ~]$ grep java.lang.Thread.State dump17 | awk '{print $2$3$4$5}' | sort | uniq -c
39 RUNNABLE
21 TIMED_WAITING(onobjectmonitor)
6 TIMED_WAITING(parking)
51 TIMED_WAITING(sleeping)
305WAITING(onobjectmonitor)
3 WAITING(parking)

分析上面的線程的每個狀態是因爲什麼原因造成的。

第三步:打開dump文件查看處於WAITING(onobjectmonitor)的線程在做什麼。

第四步:減少JBOSS的工作線程數,找到JBOSS的線程池配置信息,將maxThreads降到100。

使用建議

原文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章