线程和指针


//1.thread

#pragma mark - 线程间共享指针

/*

  两个向量指针,sum字段(持有点积),length字段(定点积函数要用的向量的长度)

  length字段表示线程处理的向量的部分,不是整个向量的长度

 */

pthread_mutex_t mutexSum;//全局区域声明它以充许多个线程访问

typedef struct {

    double *vectorA;

    double *vectorB;

    double sum;

    int length;

}VectorInfo;


/*

 VectorInfo指针和计算点积向量的起始索引

 */

typedef struct {

    VectorInfo *info;

    int beginningIndex;

}Product;


/*

 所有线程会在同一时间对两个向量进行计算,但是它们访问的是向量的不同部分,所以不会有冲突。

 每个线程会计算自己负责的那些向量的各,不过,这个各需要累加到VectorInfo结构体的sum字段上。

 多个线程可能会同时访问sum字段,所以需要用互斥锁保护数据,下面会声明互斥锁。同一时间互斥锁只允许

 一个线程访问受保护的变量,声明互斥锁保护sum变量,在全局区域声明它以充许多个线程访问

 */

void dotProduct(void *prod){

    Product *product = (Product *)prod;

    VectorInfo *vectorInfo = product->info;

    int beginningIndex = product->beginningIndex;

    int endingIndex = beginningIndex +vectorInfo->length;

    

    double total = 0;

    for (int i = beginningIndex; i<endingIndex;i++) {

        total +=(vectorInfo->vectorA[i] *vectorInfo->vectorB[i]);

    }

    

    pthread_mutex_lock(&mutexSum);

    vectorInfo->sum += total;

    pthread_mutex_unlock(&mutexSum);

    

    pthread_exit((void *)0);

}


#define NUM_THREADS 4

void threadExample(){

    VectorInfo vectorInfo;

    double vectorA[]={1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0

    };

    double vectorB[]={1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0

    };

    

    vectorInfo.vectorA = vectorA;

    vectorInfo.vectorB = vectorB;

    vectorInfo.length = 4;

    

    //创建4个元素的线程数组,初始化互斥锁和线程的属性字段

    pthread_t threads[NUM_THREADS];

    

    void *status;

    pthread_attr_t attr;

    

    pthread_mutex_init(&mutexSum,NULL);

    pthread_attr_init(&attr);

    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);

    

    int returnValue;

    int threadNumber;

    

    //每次迭代都会创创建一个新的Product实例,会把vectorInfo的地址和一个基于threadNumber得到的唯一索引赋给它。

    //然后创建线程

    for (threadNumber = 0; threadNumber <NUM_THREADS; threadNumber ++) {

        Product *product = (Product *)malloc(sizeof(Product));

        product->beginningIndex = threadNumber *4;

        product->info = &vectorInfo;

        returnValue = pthread_create(&threads[threadNumber], &attr, (void *)dotProduct,(void *)product);

        

        if (returnValue) {

            printf("ERROR,Unable to create thread:%d\n",returnValue);

            exit(-1);

        }

    }

    

  //loop结束,销毁线程属性和互斥锁,for循环确保程序等到4个线程都完成后打印点积

    pthread_attr_destroy(&attr);

    for (int i =0; i<NUM_THREADS; i++) {

        pthread_join(threads[i], &status);

    }

    pthread_mutex_destroy(&mutexSum);

    printf("Dot Product sum:%lf\n",vectorInfo.sum);

    pthread_exit(NULL);

}


//factorial

#pragma mark - 用函数指针支持回调

/*

1.回调定义:如果一个线程的事件导致另一个线程的函数调用。将回调函数的指针传递给线程,

  而函数的某个事件会引发对回调函数的调用,这种方法在GUI应用程序中处理用户线程事件很有用。

2.factorial:阶乘,结果和回调函数指针。用这些数据计算阶乘,把结果保存到result字段,

  调用回调函数,然后结束线程

 */

typedef struct _factorialData{

    int number;

    int result;

    void (*callBack)(struct_factorialData *);

}FactorialData;


void factorial(void *agrs){

    FactorialData *factorialData = (FactorialData*)agrs;

    void(*callBack)(FactorialData*);

    

    int number = factorialData->number;

    callBack = factorialData->callBack;

    

    int num = 1;

    for (int i =1; i<=number; i++) {

        num *= i;

    }

    

    factorialData->result = num;

    callBack(factorialData);

    pthread_exit(NULL);

    

}


void startThread(FactorialData *data){

    pthread_t thread_id;

    int thread = pthread_create(&thread_id,NULL,(void *(*)(void *))factorial, (void *)data);

    if (thread) {

        printf("ERROR,Unable to create thread:%d\n",thread);

        exit(-1);

    }

}


void callBackFunction(FactorialData *factorialData){

    printf("Factorial is %d \n",factorialData->result);

}


void initThread(){

    FactorialData *datas = (FactorialData *)malloc(sizeof(FactorialData));

    

    if (!datas) {

        printf("Faild to allocate memory\n");

        return  ;

    }

    datas->number = 8;

    datas->callBack =callBackFunction;

    

    startThread(datas);

    

    sleep(2000);//为所有线程正常结束提供足够的时间

}


//2.pointer alias

/*

 指针的别名,如果两个指针引用同一内存地址,我们称一个指针是另一个指针的别名。别名并不罕见,不过可能会引发一些问题

 强别名:它不允许一种类型的指针成为另一种类型的指针的别名

 

 C是类型语言,在声明变量时就得为其指定类型,可以存在不同类型的多个变量

 有时可能需要把一种类型转换成另一种类型,这一般是通过类型转换实现的,不过也可能使用联合体,类型双关就是指这种绕开

 类型系统的技术


 如果转换涉及指针,可能会产生严重的问题。为了说明这种技术,函数会判断一个浮点数是否为正,

 这个可以正确工作,也不会涉及别名,因为没有用到指针

 */

typedef union _conversion{

    float fNum;

    unsigned int uiNum;

}Conversion;


int isPositivel(float number){

    Conversion conversion ={.fNum = number};

    return (conversion.uiNum & 0x80000000)==0;

}

float number = 3.25f;

unsigned int *ptrValue = (unsigned int *)&number;

unsigned int result = (*ptrValue & 0x80000000) == 0;

NSLog(@"result = %d",result);


/*3.

 restric关键字可以在声明指针时告诉编译器这个指针没有别名,这样就允许编译器产生更高效的代码。

  很多情况下这是通过缓存指针实现的,不过,编译器也可以选择不优化代码,如果用了别名,那么执代码会导致

  未定义行为,编译器不会因为破坏强别名假设而提供任何警告信息

 

 volatile关键字可以阻止运行时系统使用寄存器暂存端口值,每次访问端口都需要系统读写端口,而不是从寄存器中读

  取一个可能已经过期的值。

  如把所有变量声明为volatile,会阻碍编译器进行所有类型的优化

*/

void add(int size,double *restrict arr1,const double *restrict arr2){

    for (int i =0; i<size ; i++) {

        arr1[i] += arr2[i];

    }

}


    

/*4.判断机器的字节序,如在Intel PC上输出,这是小字节序架构,内存中分配:

    //100:78

    //101:56

    //102:34

    //103:12

*/

int num = 0x12345678;

char *pc = (char *)&num;

for (int i =0; i<4; i++) {

   NSLog(@"%p:%02x",pc,(unsignedchar)*pc++);

}


int main(int argc,constchar * argv[]) {

    threadExample();

    initThread();   

    double vector1[] = {1.1,2.2,3.3,4.4};

    double vector2[] = {1.1,2.2,3.3,4.4};

    double *vector3 = vector2;

    add(4,vector1,vector2);

    NSLog(@"%d",isPositivel(-3.2));


    return 0;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值