執行緒安全-一個VC下多個網路請求

躍然發表於2014-10-27

一、執行緒安全變數控制顯示隱藏loading框

問題描述:

同一頁面有兩個非同步網路請求,第一個請求開始,loading旋轉,第二個請求開始loading旋轉,第一個結束,loading停止旋轉,可是這時第二個請求還沒有結束,然後loading就結束了,於是問題就來了。


解決方案:




二、由上面問題引申出的問題:

1. #import <libkern/OSAtomic.h> 


這段話是從網上copy過來的,總結了一下原子操作的作用。但是文中提到的osbase.h檔案找不到。可能是因為版本升級我的lib中沒有這個檔案。

iOS平臺下的原子操作函式都以OSAtomic開頭,使用時需要包含標頭檔案<libkern/OSBase.h>。不同執行緒如果通過原子操作函式對同一變數進行操作,可以保證一個執行緒的操作不會影響到其他執行緒內對此變數的操作,因為這些操作都是原子式的。因為原子操作只能對內建型別進行操作,所以原子操作能夠同步的執行緒只能位於同一個程式的地址空間內。

轉載請說明下:謝謝了。

點選開啟連結http://blog.csdn.net/a21064346/article/details/8076972


單例方式1

  1. + (ABAddressBook *) sharedAddressBook  
  2. {  
  3.     static ABAddressBook * volatile __shared = nil;  
  4.       
  5.     if ( __shared == nil )  
  6.     {  
  7.         ABAddressBook * tmp = [[ABAddressBook alloc] init];  
  8.         if ( OSAtomicCompareAndSwapPtr(nil, tmp, (void * volatile *)&__shared) == false )  
  9.             [tmp release];  
  10.     }  
  11.       
  12.     return ( __shared );  
  13. }  

上面一段程式碼是建立一個 ABAddressBook的單例,為了保證在呼叫shareAddressBook的時候,記憶體中只有一個且記憶體地址唯一(也就是說,怕其他執行緒訪問到這個函式,同時進行訪問這個單例)

volatile的作用是每次取得數值得方式是直接從記憶體中讀取。


單例方式2

  1. + (ILSCMPersistenceManage *)sharedInstance {  
  2.     @synchronized ([ILSCMPersistenceManage class]) {  
  3.         if (__sharedInstance) {  
  4.             return __sharedInstance;  
  5.         }  
  6.         __sharedInstance = [[ILSCMPersistenceManage alloc] init];  
  7.         return __sharedInstance;  
  8.     }  
  9. }  


二者區別:

前者:更區域資料的底層,從更深層來進行對單例的保護,而且不僅僅是作用於指標,還有其他的資料格式。並且它並沒有去阻斷其他執行緒來對函式的訪問

後者:加鎖,對程式碼的執行效率與前者相比要低一些。如果運用在其他資料,而這個資料被更新的速度很快,那麼效率就很差了。


參考與學習:

1、http://southpeak.github.io/blog/2014/10/17/osatomicyuan-zi-cao-zuo/

2、http://www.cocoachina.com/industry/20130821/6842.html

3http://southpeak.github.io/blog/2014/10/25/objective-c-runtime-yun-xing-shi-zhi-lei-yu-dui-xiang/


2.OSAtomic vs OSAtomicBarrier


On Intel and uniprocessor platforms, it doesn't matter.

For multiprocessor PPC systems, you should always use the barrier variety of functions, unless the atomic store affects no dataother than the atomic variable.

The following would not be ok:

data_structure[y].data++;

OSAtomicIncrement32(y);

You must use a barrier here, because other threads may see data_structure as out of date.

However, if you are using an atomic variable for some purpose where it stands alone, you may omit the barrier:

// y is not used to access any other data

OSAtomicIncrement32(y);

Fine, as long as the value of y does not affect the variable of any shared data structure.

Essentially, it's a cache flush. You can always safely use the barrier functions, but in some cases, you may be able to improve performance by not using the barrier functions, such as if y is not used relative to a data structure. There are probably not many cases where you can use the functions without the barrier.


3.int int32_t int64_t


這些事跨平臺程式設計導致的;

一、資料型別特別是int相關的型別在不同位數機器的平臺下長度不同。C99標準並不規定具體資料型別的長度大小,只規定級別。作下比較:

16位平臺

char         1個位元組8

short        2個位元組16

int            2個位元組16

long         4個位元組32

指標         2個位元組


32位平臺

char         1個位元組8

short        2個位元組16

int            4個位元組32

long         4個位元組

long long 8個位元組

指標         4個位元組


64位平臺

char         1個位元組

short        2個位元組

int            4個位元組

long         8個位元組(區別)

long long 8個位元組

指標        8個位元組(區別)


二、程式設計注意事項

為了保證平臺的通用性,程式中儘量不要使用long資料庫型。可以使用固定大小的資料型別巨集定義:

typedef signed char       int8_t

typedef short int             int16_t;

typedef int                      int32_t;

# if __WORDSIZE == 64

typedef long int              int64_t;

# else

__extension__

typedef long long int      int64_t;

#endif


三、使用int時也可以使用intptr_t來保證平臺的通用性,它在不同的平臺上編譯時長度不同,但都是標準的平臺長度,比如64位機器它的長度就是8位元組,32位機器它的長度是4位元組,定義如下:

#if __WORDSIZE == 64

typedef long int                intptr_t;

#else

typedef int                        intptr_t;

#endif

程式設計中要儘量使用sizeof來計算資料型別的大小

以上型別定義都有相應的無符號型別。

另外還有ssize_tsize_t分別是sign size_tunsigned signed size of computer word size。它們也是表示計算機的字長,在32位機器上是int型,在64位機器上long型,從某種意義上來說它們等同於intptr_t uintptr_t。它們在stddef.h裡面定義。需要注意的是socketaccept函式在有些作業系統上使用size_t是不正確的,因為 accept接收的int*型別,而size_t可能是long int 型別。後來BSD使用sock_t來替代它。

uint8_t / uint16_t / uint32_t /uint64_t 是什麼資料型別

nesc的程式碼中,你會看到很多你不認識的資料型別,比如uint8_t等。咋一看,好像是個新的資料型別,不過C語言(nescC的擴充套件)裡面好像沒有這種資料型別啊!怎麼又是u又是_t的?很多人有這樣的疑問。論壇上就有人問:以*_t結尾的型別是不是都是long型的?在baidu上查一下,才找到答案,這時才發覺原來自己對C掌握的太少。

那麼_t的意思到底表示什麼?具體的官方答案沒有找到,不過我覺得有個答案比較接近。它就是一個結構的標註,可以理解為type/typedef的縮寫,表示它是通過typedef定義的,而不是其它資料型別。

uint8_tuint16_tuint32_t等都不是什麼新的資料型別,它們只是使用typedef給型別起的別名,新瓶裝老酒的把戲。不過,不要小看了typedef,它對於你程式碼的維護會有很好的作用。比如C中沒有bool,於是在一個軟體中,一些程式設計師使用int,一些程式設計師使用short,會比較混亂,最好就是用一個typedef來定義,如:
typedef char bool;

一般來說,一個C的工程中一定要做一些這方面的工作,因為你會涉及到跨平臺,不同的平臺會有不同的字長,所以利用預編譯和typedef可以讓你最有效的維護你的程式碼。為了使用者的方便,C99標準的C語言硬體為我們定義了這些型別,我們放心使用就可以了。

 按照posix標準,一般整形對應的*_t型別為:
1位元組     uint8_t
2位元組     uint16_t
4位元組     uint32_t
8位元組     uint64_t

相關文章