iOS开发之多线程笔记(二)之pthread

2018-01-10  本文已影响21人  番茄炒西红柿啊

pthread在中使用不多,我这个小码农也是偶然间才在网上看到的,于是就浅显的了解了一下.介绍概念什么的请自行Google.这里直接开始撸代码

#pragma mark - Event Response
- (void)pThread_test {
    self.count = 1000;
    for(int i = 0; i < 4; i++) {
        [self create_pThread];
    }
}

- (void)create_pThread {
    //创建线程对象
    pthread_t thread;
    //创建线程
    /*
     参数:
     1.指向线程标识符的指针,C 语言中类型的结尾通常 _t/Ref,而且不需要使用 *;
     2.用来设置线程属性;
     3.指向函数的指针,传入函数名(函数的地址),线程要执行的函数/任务;
     4.运行函数的参数;
     */
    int success = pthread_create(&thread, NULL, run, &(_count));
    if(success == 0) {
        /*
         c语言中,有时成功及成功,错误却会有很多种原因
         所以这里返回0表示开辟线程成功
         非0表示失败开启线程失败
         */
        NSLog(@"开启线程...");
    }
    //这里需要手动设置子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源.否则不会释放.
    pthread_detach(thread);
}

void *run(void* sender) {
    while (1) {
        int* s = sender;
        int count = *s;
        if(count <= 0) {
            break;
        }
        test(s);
    }
    return NULL;
}

void test(int *count) {    
    *count = *count - 1;
    NSLog(@"%d", *count);
}

ok代码就这样,看起来貌似没问题.cmd+R

1.png
结果有点不遂人愿.这里有2个子线程对count操作后,返回的结果却是一样的.这就和我们所需要的逻辑不和了.我们所期望的是每一个线程做完减一操作后,下一个线程再来操作应该是在减一的基础上减一.所以是不可以出现2个线程都操作完之后结果是一样的场景.此结果也不符合逻辑.
这就是我们常说要注意的线程安全问题 有个变量,你在一个线程中修改它的值,同时在另一个线程中也改了它的值.这个时候你再去读这个值的时候,很可能这个值,就不是你所预期的了.

这里我们需要给run这个方法内部添加一个线程锁,来保证一次只能有一个线程进入来操作数据

void *run(void* sender) {
    if(!condition) {
        condition = [[NSCondition alloc] init];
    }
    while (1) {
        [condition lock];
        int* s = sender;
        int count = *s;
        if(count <= 0) {
            [condition unlock];
            break;
        }
        test(s);
        [condition unlock];
    }
    return NULL;
}

加锁的方式有很多,以后再专门总结一下,这里暂时就用这一种.加锁后,结果就和预期的一样了.

swift相关代码在网上相关介绍不多,自己倒腾了下,顺便贴上swift代码:

let run : @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? =
    { (pktlist:UnsafeMutableRawPointer) in
        while true {
            condition.lock()
            let p:UnsafeMutableRawPointer = pktlist
            let t = p.assumingMemoryBound(to: Int.self)
            guard t.pointee > 0 else {
                condition.unlock()
                break;
            }
            t.pointee -= 1;
            NSLog("%d", t.pointee)
            condition.unlock()
        }
        return nil
    }

    @objc private func pThread_test() -> Void
    {
        self.count = 1000
        for i in 0..<4
        {
            if i < 4
            {
                let pthread: UnsafeMutablePointer<pthread_t?> = UnsafeMutablePointer<pthread_t?>.allocate(capacity: MemoryLayout<pthread_t?>.size)
                let param = UnsafeMutableRawPointer(&count)
                let success = pthread_create(pthread, nil, self.run, param)
                if success == 0 {
                    NSLog("开启线程...")
                }
                pthread_detach((pthread.pointee)!)
                pthread.deinitialize()
                pthread.deallocate(capacity: MemoryLayout<pthread_t?>.size)
            }
        }
    }
上一篇下一篇

猜你喜欢

热点阅读