首页 > 代码库 > 线程安全-一个VC下多个网络请求

线程安全-一个VC下多个网络请求

一、线程安全变量控制显示隐藏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的project中一定要做一些这方面的工作,由于你会涉及到跨平台。不同的平台会有不同的字长,所以利用预编译和typedef能够让你最有效的维护你的代码。为了用户的方便,C99标准的C语言硬件为我们定义了这些类型,我们放心使用就能够了。

 依照posix标准。一般整形相应的*_t类型为:
1字节     uint8_t
2字节     uint16_t
4字节     uint32_t
8字节     uint64_t

线程安全-一个VC下多个网络请求