線程:markdown
- 線程是進程的基本執行單元,一個進程的全部任務都在線程中執行
- 進程要想執行任務,必須得有線程,進程至少要有一條線程
- 程序啓動會默認開啓一條線程,這條線程被稱爲主線程或 UI 線程
進程:多線程
- 進程是指在系統中正在運行的一個應用程序
- 每一個進程之間是獨立的,每一個進程均運行在其專用的且受保護的內存空間內
- 經過「活動監視器」能夠查看 Mac 系統中所開啓的進程
地址空間:同一進程的線程共享本進程的地址空間,而進程之間則是獨立的地址空間。 資源擁有:同一進程內的線程共享本進程的資源如內存、I/O、cpu等,可是進程之間的 資源是獨立的。併發
- 一個進程崩潰後,在保護模式下不會對其餘進程產生影響,可是一個線程崩潰整個進程都死掉。因此多進程要比多線程健壯。
- 進程切換時,消耗的資源大,效率高。因此涉及到頻繁的切換時,使用線程要好於進程。一樣若是要求同時進行而且又要共享某些變量的併發操做,只能用線程不能用進程
- 執行過程:每一個獨立的進程有一個程序運行的入口、順序執行序列和程序入口。可是 線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
- 線程是處理器調度的基本單位,可是進程不是。
- 線程沒有地址空間,線程包含在進程地址空間中
優勢:性能
- 能適當提升程序的執行效率
- 能適當提升資源的利用率(CPU,內存)
- 線程上的任務執行完成後,線程會自動銷燬
缺點atom
- 開啓線程須要佔用必定的內存空間(默認狀況下,每個線程都佔 512 KB)
- 若是開啓大量的線程,會佔用大量的內存空間,下降程序的性能
- 線程越多,CPU 在調用線程上的開銷就越大
* 程序設計更加複雜,好比線程間的通訊、多線程的數據共享spa
時間片的概念:CPU在多個任務直接進行快速的切換,這個時間間隔就是時間片線程
* (單核CPU)同一時間,CPU 只能處理 1 個線程 * 換言之,同一時間只有 1 個線程在執行設計
* 多線程同時執行: * 是 CPU 快速的在多個線程之間的切換3d
* 若是線程數很是多code
* 每一個線程被調度的次數會下降,線程的執行效率下降
__bridge
只作類型轉換,可是不修改對象(內存)管理權;__bridge_retained
(也可使用CFBridgingRetain
)將Objective-C的對象轉換爲 Core Foundation的對象,同時將對象(內存)的管理權交給咱們,後續須要使用 CFRelease或者相關方法來釋放對象;__bridge_transfer
(也可使用CFBridgingRelease
)將Core Foundation
的對象 轉換爲Objective-C的對象,同時將對象(內存)的管理權交給ARC。這四種拒絕策略均實現的RejectedExecutionHandler接口
在看優先級反轉前先了解什麼是IO密集型線程和CPU密集型線程。
IO密集型線程比CPU密集型線程更容易獲得優先級提高。
特殊場景下,當多個優先級都比較高的CPU 密集型線程霸佔了全部 CPU 資源,而此時優先級較低的 IO 密集型線程將持續等待,產生線程餓死的現象。固然,爲了不線程餓死,CPU會發揮調度做用去逐步提升被「冷落」線程的優先級(提升優先級不必定就會執行,有機率的問題),IO 密集型線程一般狀況下比 CPU 密集型線程更容易獲取到優先級提高。
在咱們使用多線程的過程當中會遇到一種現象,就是資源搶奪。
例如多窗口售票這個案例,假設如今有 1000 張票,窗口 1 售賣了一張還剩 999 張,可是窗口 2 並不能同步知道剩餘票數,因此仍是按照 1000 張去售票,這種狀況就會出現問題。這個時候咱們就須要藉助加鎖操做來解決這種問題。這裏咱們介紹兩種鎖,自旋鎖與互斥鎖。
互斥鎖:
互斥鎖參數:
自旋鎖:
互斥鎖與自旋鎖的區別:
atomic:
atomic
是原子屬性,是爲多線程開發準備的,是默認屬性!setter
方法中,增長了鎖(自旋鎖),可以保證同一時間,只有一條線程對屬性進行寫
操做nonatomic:
nonatomic
是非原子屬性下面咱們來看一下 atomic
的底層實現:
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
if (offset == 0) {
object_setClass(self, newValue);
return;
}
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:nil];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:nil];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
// 判斷是不是 atomic 標識,是的話就添加鎖操做
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spinlock_t& slotlock = PropertyLocks[slot];
slotlock.lock();
oldValue = *slot;
*slot = newValue;
slotlock.unlock();
}
objc_release(oldValue);
}
複製代碼
在源碼中咱們能夠看到 atomic
其實就是一個標識,底層根據 atomic
標識來判斷是否加鎖。