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

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


这段话是从网上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.

 */

bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue )


+ (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的转载)


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

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


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

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

后者:加锁,对代码的执行效率与前者相比要低一些。如果运用在其他数据,而这个数据被更新的速度很快,那么效率就很差了。