您的位置:首页 > 移动开发 > IOS开发

OSATOMIC.h的介绍 OSATOMIC与synchronized 加锁的对比 iOS开发 多线程编程 .

2012-11-22 19:17 369 查看
这段话是从网上copy过来的,总结了一下原子操作的作用。但是文中提到的osbase.h文件找不到。可能是因为版本升级我的lib中没有这个文件。
iOS平台下的原子操作函数都以OSAtomic开头,使用时需要包含头文件<libkern/OSBase.h>。不同线程如果通过原子操作函数对同一变量进行操作,可以保证一个线程的操作不会影响到其他线程内对此变量的操作,因为这些操作都是原子式的。因为原子操作只能对内置类型进行操作,所以原子操作能够同步的线程只能位于同一个进程的地址空间内。

转载请说明下:谢谢了。
点击打开链接

(http://blog.csdn.net/a21064346/article/details/8076972)

#import<libkern/OSAtomic.h>
导入这个文件,可以调用里面的函数,来保证变量的数值。

/*! @header
 * These are the preferred versions of the atomic andsynchronization operations.
 * Their implementation is customized at boot time for the platform, including
 * late-breaking errata fixes as necessary.   They are thread safe.
 *
 * WARNING: all addresses passed to these functions must be "naturally aligned",
 * i.e.  * <code>int32_t</code> pointers must be 32-bit aligned (low 2 bits of
 * address are zeroes), and <code>int64_t</code> pointers must be 64-bit aligned
 * (low 3 bits of address are zeroes.)
 *
 * Note that some versions of the atomic functions incorporate memory barriers
 * and some do not.  Barriers strictly order memory access on weakly-ordered
 * architectures such as PPC.  All loads and stores that appear (in sequential
 * program order) before the barrier are guaranteed to complete before any
 * load or store that appears after the barrier.
 *
 * On a uniprocessor system, the barrier operation is typically a no-op.  On a
 * multiprocessor system, the barrier can be quite expensive on some platforms,
 * such as PPC.
(这段话告诉我们,如果是一个多处理器的系统,运用OSATOMIC.h是显得非常有价值的。确实,因为这个东西就是为了在多线程中保证数据不会错乱,得到的数值是你最想得到的那一个,尽管它在随时变化)
 *
 * Most code should use the barrier functions to ensure that memory shared between
 * threads is properly synchronized.  For example, if you want to initialize
 * a shared data structure and then atomically increment a variable to indicate
 * that the initialization is complete, you must use {@link OSAtomicIncrement32Barrier}
 * to ensure that the stores to your data structure complete before the atomic
 * increment.
 *
 * Likewise, the consumer of that data structure must use {@link OSAtomicDecrement32Barrier},
 * in order to ensure that their loads of the structure are not executed before
 * the atomic decrement.  On the other hand, if you are simply incrementing a global
 * counter, then it is safe and potentially faster to use {@link OSAtomicIncrement32}.
 *
 * If you are unsure which version to use, prefer the barrier variants as they are
 * safer.
 *
 * The spinlock and queue operations always incorporate a barrier.
 *
 * For the kernel-space version of this header, see
 * {@link //apple_ref/doc/header/OSAtomic.h OSAtomic.h (Kernel Framework)}
 *
 * @apiuid //apple_ref/doc/header/user_space_OSAtomic.h
 */ 
(这里说明的是 如何使用这些函数,要求格式的一一对应。下面取一个指针的格式来进行举例)
ps:因为函数过多,具体的一些其他函数,你可以自己取查看OSATOMIC.h

/*! @abstract Compare and swap pointers.
    @discussion
This function compares the pointer stored in <code>__oldValue</code> to the pointer
in the memory location referenced by <code>__theValue</code>.  If the pointers
match, this function stores the pointer from <code>__newValue</code> into
that memory location atomically.
    @result Returns TRUE on a match, FALSE otherwise.
 */
boolOSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue )

[csharp]
view plaincopyprint?

+ (ABAddressBook *) sharedAddressBook  
{  
    static ABAddressBook * volatile __shared = nil;  
      
    if ( __shared == nil )  
    {  
        ABAddressBook * tmp = [[ABAddressBook alloc] init];  
        if ( OSAtomicCompareAndSwapPtr(nil, tmp, (void * volatile *)&__shared) == false )  
            [tmp release];  
    }  
      
    return ( __shared );  
}  

上面一段代码 是创建一个 ABAddressBook的单例,为了保证在 调用shareAddressBook的时候,内存中只有一个且内存地址唯一(也就是说,怕其他线程访问到这个函数,同时进行访问这个单例)

volatile的作用是 每次取得数值得方式 是直接从内存中读取。(具体见 blog中volatile的转载)

目前本人使用的方法中,保证单例的 安全,类似做法如下

[csharp]
view plaincopyprint?

+ (ILSCMPersistenceManage *)sharedInstance {  
    @synchronized ([ILSCMPersistenceManage class]) {  
        if (__sharedInstance) {  
            return __sharedInstance;  
        }  
        __sharedInstance = [[ILSCMPersistenceManage alloc] init];  
        return __sharedInstance;  
    }  
}  

至于两者的区别,个人总结:

前者:更区域数据的底层,从更深层来进行对 单例的保护,而且不仅仅是作用于指针,还有其他的数据格式。并且它并没有去阻断 其他线程来对 函数的访问

后者:加锁,对代码的执行效率与前者相比要低一些。如果运用在其他数据,而这个数据被更新的速度很快,那么效率就很差了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: