首页 > 代码库 > 线程安全变量控制显示隐藏loading框

线程安全变量控制显示隐藏loading框

一、线程安全变量控制显示隐藏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

线程安全变量控制显示隐藏loading框