1. 程式人生 > >iOS 執行緒同步幾種方式

iOS 執行緒同步幾種方式

多執行緒同步目的有以下幾個方面:第一,對一段程式碼的執行進行保護,如果同時執行一段程式碼,中間的臨時變數可能會互相干擾造成結果不對;第二,對資源的保護,多個執行緒執行不同的程式碼,但是可能涉及同一個資源;第三,訊息傳遞,一個執行緒通知另外一個執行緒發生了一件事。

iOS中常用執行緒同步方式:

NSLock

一個封裝了pthread_mutex的OC物件,常用於保護一個程式碼塊,如果NSLock物件已經被lock,當前執行緒放棄時間片並阻塞,等待鎖的釋放。

可以通過lockBeforeDate:限制一個鎖定的時間,獲取鎖的時候也可以使用tryLock:來避免阻塞。

NSLock有3點要注意:unlock的執行執行緒必須和lock相同,否則行為未定義;在同一個執行緒上lock兩次會造成死鎖;向未lock的物件傳送unlock會造成Crash。

NSRecursiveLock

NSRecursiveLock也是封裝了一個pthread_mutex,和NSLock不同的是在NSLock中pthread_mutex的型別是 PTHREAD_MUTEX_ERRORCHECK,而在NSRecursiveLock中pthread_mutex的型別是PTHREAD_MUTEX_RECURSIVE。

在同一個執行緒上lock兩次會造成死鎖,但是一個執行緒在請求鎖之前可能不知道這個鎖是否已經被鎖定,亦或一個函式可能會被多次或者遞迴呼叫,如果貿然加鎖,就會造成死鎖,此種情況下,應該使用NSRecursiveLock。NSRecursiveLock允許一個執行緒多次獲取鎖(同時需要相應的釋放次數),對於沒有獲取鎖的執行緒而言,與NSLock功能一致。

NSConditionLock & NSCondition

NSLock是比較簡單的鎖,一個執行緒申請鎖,然後其他執行緒等待,當這個執行緒釋放鎖的時候,等待的執行緒哪個會被喚醒沒有定義。如果仍然使用NSLock,此時的解決方案就是執行緒在釋放鎖之前設定一個全域性的狀態,然後等待的執行緒獲取鎖之後,檢視狀態,如果不是自己要處理的情況,就釋放鎖,重新進入迴圈。但是這種方案有不可預測性,因為不知道應該被喚起的執行緒何時能獲取到鎖,其他執行緒不停的被喚起等待效能損失也非常大。

NSConditionLock就是解決這種情況的。NSConditionLock把條件變數封裝到了鎖中,核心根據是否滿足等待條件來決定是否讓執行緒獲得鎖。有兩個核心API:

-lockWhenCondition:如果滿足條件,就獲取鎖。

-unlockWithCondition:設定一個獲取鎖的條件並解鎖。

dispatch_semaphore_t

考慮另外一種場景,一個執行緒是生產者,生產了3個產品,然後有5個消費者執行緒等待。這是介於NSLock和NSConditionLock之間的場景,第一是有條件的,一共就3個產品;第二,不用區分執行緒,只要喚醒3個就可以。這時候無論使用NSLock還是使用NSConditionLock都不太方便。

dispatch_semaphore_t就是在這樣的場景下使用。dispatch_semaphore_t解決方案有3個核心函式:

dispatch_semaphore_create,建立一個訊號量,指定資源個數。

dispatch_semaphore_wait,等待訊號量,如果資源已經為0則阻塞執行緒,當資源大於0的時候被喚醒。

dispatch_semaphore_signal,傳送一個訊號量,將資源數+1。

這裡還有一個邏輯,就是如果資源數已經達到了初識設定的3個,生產者執行緒再signal也會被阻塞。在實際工程中,這個機制可以保護產品佇列的大小。

dispatch_barrier_async & dispatch_barrier_sync

還有一種場景,就是多個執行緒訪問一個資源,對於讀可以併發,但是對於寫需要獨佔,也就是所謂的讀寫鎖。

使用GCD的API可以實現這個需求。把一個block使用barrier的方式提交到並行佇列中,一旦這個block開始執行,佇列中其他的block就不能執行直到這個block執行完成。可以把寫操作寫在這個block中,然後讀操作寫在另外的block中使用一般的提交。就能實現讀併發,寫獨佔。

dispatch_barrier_async和dispatch_barrier_sync的區別是dispatch_barrier_sync會阻塞執行緒,直到提交的block執行完畢。

需要注意的是,要自己建立並行佇列,官方文件給出:

The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_async function.

其實,對於讀寫鎖,更好理解的是pthread_rwlock系列函式。

相關推薦

iOS 執行同步方式

多執行緒同步目的有以下幾個方面:第一,對一段程式碼的執行進行保護,如果同時執行一段程式碼,中間的臨時變數可能會互相干擾造成結果不對;第二,對資源的保護,多個執行緒執行不同的程式碼,但是可能涉及同一個資源;第三,訊息傳遞,一個執行緒通知另外一個執行緒發生了一件事。

4. 執行同步方式

執行緒同步的方式主要有以下四種:臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別。 他們的主要區別和特點如下: 1)臨界區:通過對多執行緒的序列化來訪問公共資源或一段程式碼,速度快,適合控制資料訪問。在任意時刻只允許一個執行緒對共

iOS NSthread & Thread 開啟執行方式

一、開啟執行緒執行指定物件的方法 /** 引數1: 執行引數2方法的物件 引數2: 開啟執行緒後執行的方法 引數3: 傳遞的物件資料(引數2的方法可以直接用) */ // OC - (

Java中建立執行方式以及執行同步方式

執行緒同步自己及基本就用過Thread和Runnable這兩種方式,還有其他很多方式如下: Executor框架簡介 建立執行緒有幾種不同的方式?你喜歡哪一種?為什麼? 而執行緒同步會用的方式就更少了,只會synchronized,其他方式如下: 關於執

設計模式之單例模式【內附物件例項化方式、實現執行安全方式

繼續來複習常用的設計模式-單例模式,順便回憶一下執行緒安全的幾種實現方式。 一、什麼是單例模式 單例模式,簡單常用的一種設計模式,也很好的體現了程式碼控制物件在記憶體數量的一種方式,主要分2種實現方式: ①餓漢式,執行緒安全 ②懶漢式,執行緒不安全(新增鎖機制,可以實現執行緒安全)

開啟執行方式

目錄 執行緒開啟方式(一)-非同步委託          建立執行緒的一種簡單方式是定義一個委託,並非同步呼叫它。 委託是方法的型別安全的引用。Delegate類 還支援非同步地呼叫方法。在後臺,Delegate類會建立一個執行任務的執行緒。

java執行同步5方式

 java允許多執行緒併發控制,當多個執行緒同時操作一個可共享的資源變數時(如資料的增刪改查),      將會導致資料不準確,相互之間產生衝突,因此加入同步鎖以避免在該執行緒沒有完成操作之前,被其他執行緒的呼叫,      從而保證了該變數的唯一性和準確性。 1

建立執行方式,以及為什麼啟動執行不用run,而用start方法!!!

首先,我們大家都知道,建立執行緒的兩種蛀主要的方法,一種是繼承Thread類,另一種是實現Runnable介面。對於第一種建立執行緒的方式有兩個不足: 1.當前執行緒重寫run方法定義該執行緒要完成的工作,這就導致了任務是定義線上程內部的,於是執行緒與任務有一個強耦合關

Android建立子執行和回撥主執行方式

一. 建立子執行緒 //通過繼承thread public class JNThread1 extends Thread { public JNThread1(String name){ super(

c#使用多執行方式示例詳解

(1)不需要傳遞引數,也不需要返回引數 ThreadStart是一個委託,這個委託的定義為void ThreadStart(),沒有引數與返回值。 複製程式碼程式碼如下: class Program { static void Main(string[] args)

java多執行與併發之建立執行方式

1、繼承Thread類方法 public class Demo1 extends Thread{ @Override public void run() { //判斷標誌 while(true) { System.out.println(get

java停止執行方式

該學習筆記是學習《java多執行緒程式設計核心技術》高洪巖版本的第一章的學習筆記,在該章節中個人認為比較重要的是如何正確的停止一個執行緒。 停止一個執行緒最重要的是讓執行緒的run方法結束執行於是可以有以下幾種方法: 1.run方法結束完成

JAVA 建立執行方式

  1.繼承 Thread 類 2. 實現 Runnable 介面 3. ExecuteService、Callable<Class>、Future 有返回值執行緒 4. 執行緒池方式   一、繼承 Thread 類,建立執行緒類 (1)定義 Thr

當阿里面試官問我:Java建立執行方式?我就知道問題沒那麼簡單

這是最新的大廠面試系列,還原真實場景,提煉出知識點分享給大家。 點贊再看,養成習慣~ 微信搜尋【武哥聊程式設計】,關注這個 Java 菜鳥。 昨天有個小夥伴去阿里面試實習生崗位,面試官問他了一個老生常談的問題:你說一說 Java 建立執行緒都有哪些方式? 這哥們心中竊喜,這個老生常談的問題早已背的滾瓜爛熟

面試官問我:建立執行方式?我笑了

## 前言 多執行緒在面試中基本上已經是必問項了,面試官通常會從簡單的問題開始發問,然後再一步一步的挖掘你的知識面。 比如,從執行緒是什麼開始,執行緒和程序的區別,建立執行緒有幾種方式,執行緒有幾種狀態,等等。 接下來自然就會引出執行緒池,Lock,Synchronized,JUC的各種併發包。然後就會

建立執行不同的方式?哪一比較受歡迎?為什麼?

有三種方式: ①繼承Thread類(真正意義上的執行緒類),是Runnable介面的實現。 ②實現Runnable介面,並重寫裡面的run方法。 ③使用Executor框架建立執行緒池。Executor框架是juc裡提供的執行緒池的實現。呼叫執行緒的start():啟動此執行緒;呼叫相應的r

Java第十三天學習筆記~多執行執行的狀態、建立執行的第二方式同步程式碼塊、同步函式)

                                 多執行緒 執行緒的狀態 CPU的執行資格:可以被C

執行實現方法?同步實現方法?

為何要使用同步? java允許多執行緒併發控制,當多個執行緒同時操作一個可共享的資源變數時(如資料的增刪改查),  將會導致資料不準確,相互之間產生衝突,因此加入同步鎖以避免在該執行緒沒有完成操作之前,被其他執行緒的呼叫,  從而保證了該變數的唯一性和準確性。 同步的

執行建立方式並實現賣票功能

本篇簡單的講下執行緒的幾種建立方式並相應的實現售票功能一、執行緒建立public class ThreadTest { public static void main(String[] args) throws InterruptedException, Executio

C++執行呼叫方式

#include<thread> #include<future> using namespace std; class A { public: void f(int x,