iOS

iOS多线程学习(一)pthread

2019-01-15  本文已影响30人  临川慕容吹雪

POSIX线程

(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程.(来源百度百科)
POSIX线程提供了一个用于创建线程的基于C的接口。

使用pthread之前,我们需要引用其对应的库头文件#import <pthread.h>

常用函数说明

关于完整相关pthreadAPI,可参考Apple文档

设置线程堆栈地址

pthread线程简单创建与参数传递

将参数传递给线程

单一参数传递实例:

- (IBAction)creatPthread:(id)sender {
    pthread_t threads[2];
    for (NSInteger i = 0; i<2; i++) {
        pthread_create(&threads[i], NULL, studyPthreadMethond, (void *)i);
    }
}

void *studyPthreadMethond(void *threadID)
{
    long tid = (long)threadID;
    NSLog(@"currentThread = %@ threadID%ld",[NSThread currentThread],tid);
    pthread_exit(NULL);
    return NULL;
}
//输出结果
 currentThread = <NSThread: 0x600001e5edc0>{number = 3, name = (null)} threadID0
 currentThread = <NSThread: 0x600001e5ecc0>{number = 4, name = (null)} threadID1

如果要传递多个参数过去,可以传递结构体过去

struct thread_TestData{
    int  thread_id;
    char *message;
};
struct thread_TestData thread_Test;
- (IBAction)creatPthread:(id)sender {
    pthread_t thread;
    thread_Test.message = "t";
    thread_Test.thread_id = 1;
    //如果thread_Test在此申明不是全局变量,会发现异步线程studyPthreadMethond里面接收不到正确的数据
    //struct thread_TestData thread_Test;
    pthread_create(&thread, NULL, studyPthreadMethond,(void *)&thread_Test);
}

void *studyPthreadMethond(void *threadData)
{
    struct thread_TestData *getData;
    getData = (struct thread_TestData *)threadData;
    NSLog(@"test %p", getData);
    int threadID = getData->thread_id;
    char *msg = getData->message;
    NSLog(@"threadID = %d message=%s %p",threadID,msg,getData->message);
    pthread_exit(NULL);
    return NULL;
}
pthread 线程加入与分离

线程加入是完成线程之间同步的一种方法
如果线程需要加入,请考虑将其明确创建为可连接。
因为并非所有实现都可以默认将线程创建为可连接
如果线程永远不需要与另一个线程连接,可考虑在分离状态下创建它。可以释放一些系统资源。

要将线程显示创建为可加入可连接或已分离状态,需要以下几步:

使用实例:

- (IBAction)joinPthread:(id)sender {
    pthread_t thread[5];
    pthread_attr_t attr;
    int pthreadCode;
    void *status;
    //初始化状态
    pthread_attr_init(&attr);
    //设置分离状态
   int detachstate = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    int getdetachstate = pthread_attr_getdetachstate(&attr, &detachstate);
    NSLog(@"getdetachstate = %d",getdetachstate);
    for (NSInteger i = 0; i<5; i++) {
        NSLog(@"MainThread:creating thread %ld\n",i);
        pthreadCode = pthread_create(&thread[i], &attr, testPthreadA, (void *)i);
        if (pthreadCode) {
            NSLog(@"retrun error code form pthread_create is %d",pthreadCode);
            exit(-1);
        }
    }
    //销毁属性对象
    pthread_attr_destroy(&attr);
    for (NSInteger i = 0; i<5; i++) {
        pthreadCode = pthread_join(thread[i], &status);
        if (pthreadCode) {
            NSLog(@"retrun error code form pthread_join is %d",pthreadCode);
            exit(-1);
        }
        NSLog(@"completed join with thread %ld having a status of %ld\n",i,(long)status);
    }
    NSLog(@"compelted.Exiting\n");
    //pthread_exit(NULL);这里调用退出会导致主线程退出
}

void *testPthreadA(void *t) {
    double result = 0;
    long pthreadID = (long)t;
    NSLog(@"Thread %ld staring..\n",pthreadID);
    for (NSInteger i = 0; i<100000; i++) {
        result =  result + i*i;
    }
    NSLog(@"Thread %ld end.Result=%lf",pthreadID,result);
    //这里返回的状态就是status状态捕获的值
    pthread_exit((void *)t);

}

打印结果如下:
getdetachstate = 0
MainThread:creating thread 0
MainThread:creating thread 1
Thread 0 staring..
MainThread:creating thread 2
MainThread:creating thread 3
Thread 1 staring..
Thread 0 end.Result=333328333350000.000000
Thread 2 staring..
MainThread:creating thread 4
Thread 3 staring..
Thread 1 end.Result=333328333350000.000000
Thread 2 end.Result=333328333350000.000000
completed join with thread 0 having a status of 0
Thread 4 staring..
completed join with thread 1 having a status of 1
Thread 3 end.Result=333328333350000.000000
completed join with thread 2 having a status of 2
Thread 4 end.Result=333328333350000.000000
completed join with thread 3 having a status of 3
completed join with thread 4 having a status of 4
compelted.Exiting

pthread 创建和销毁互斥锁

pthread中的互斥锁的基本概念:在任何给定时间只有一个线程可以锁定(或拥有)互斥变量。因此,即使多个线程试图锁定互斥锁,也只有一个线程会成功。在拥有线程解锁该互斥锁之前,没有其他线程可以拥有该互斥锁。线程必须“轮流”访问受保护的数据。
这个也是实现线程同步的一种方法。

相关函数

动态初始化初始化互斥变量.还可以静态pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;初始化互斥变量

使用实例

//互斥锁的使用
- (IBAction)lockPthread:(id)sender {
    pthread_attr_t attr;
    pthread_t thread[5];
    void *status;
    sum = 0;
    //初始化互斥锁
    pthread_mutex_init(&mutexSum, NULL);
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    for (NSInteger i =0 ; i<5; i++) {
        pthread_create(&thread[i], &attr, testPthreadB, (void *)i);
    }
    pthread_attr_destroy(&attr);
    for (NSInteger i =0 ;i<5;i++) {
        pthread_join(thread[i],&status);
    }
    NSLog(@"sum = %lf",sum);
    //销毁互斥锁
    pthread_mutex_destroy(&mutexSum);
}

void *testPthreadB(void *t) {
    int start,end,offset;
    offset = (int)t;
    start = offset *100;
    end = start +100;
    double mysum = 0;
    for (NSInteger i = start; i<end; i++) {
        mysum +=i;
    }
    //加锁
    pthread_mutex_lock(&mutexSum);
    sum +=mysum;
    NSLog(@"被访问thread %ld",offset);
    //解锁
    pthread_mutex_unlock(&mutexSum);
    pthread_exit((void *)t);
}
  

pthread 条件变量

条件变量为线程提供了另外一种同步方式。允许线程根据数据的实际值进行同步。条件变量需与互斥锁一起结合使用。

相关函数

动态创建条件变量。同样也可以通过pthread_cond_t mycondT = PTHREAD_COND_INITIALIZER 静态创建。
attr对象用于设置条件变量属性。只为条件变量定义了一个属性:process-shared,它允许条件变量被其他进程中的线程看到

当有多个线程处于阻塞状态,用来取代pthread_cond_signal

使用实例

//线程阻塞和唤醒
- (IBAction)waitPthread:(id)sender {
    count = 0;
    pthread_t thread[3];
    pthread_attr_t attr;
    pthread_mutex_init(&myMutex, NULL);
    pthread_attr_init(&attr);
    pthread_cond_init(&myCond, NULL);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&thread[0], &attr, lookCount, (void *)1);
    pthread_create(&thread[1], &attr, addCount, (void *)2);
    pthread_create(&thread[2], &attr, addCount, (void *)3);
    for (NSInteger i =0; i<3; i++) {
        pthread_join(thread[i], NULL);
    }
    NSLog(@"线程执行完毕");
    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&myMutex);
    pthread_cond_destroy(&myCond);
}

void *addCount(void *t) {
    long threadID = (long)t;
    for (NSInteger i =0; i<limit; i++) {
        pthread_mutex_lock(&myMutex);
        count ++;
        if (count == limit) {
            pthread_cond_signal(&myCond);
            NSLog(@"addcount():thread %ld count = %d 数量已经达到设定值\n",threadID,count);
        }
         NSLog(@"addcount():thread %ld count = %d 将要解锁\n",threadID,count);
        pthread_mutex_unlock(&myMutex);
        NSLog(@"addcount():thread %ld解锁完毕\n",threadID);
    }
    pthread_exit(NULL);
}

void *lookCount(void *t) {
     long threadID = (long)t;
    NSLog(@"lookCount():start thread %ld\n",threadID);
    pthread_mutex_lock(&myMutex);
    while (count<limit) {
        pthread_cond_wait(&myCond, &myMutex);
        NSLog(@"lookCount(): thread %ld 信号收到 count = %d \n",threadID,count);
    }
    count +=10;
    NSLog(@"lookCount():thread %ld count = %d 将要解锁\n",threadID,count);
    pthread_mutex_unlock(&myMutex);
    pthread_exit(NULL);
}
输出结果

参考:
POSIX Threads Programming

下一篇:
iOS多线程学习二NSTread

上一篇 下一篇

猜你喜欢

热点阅读