多线程具体实现(下)

简介: 多线程具体实现

多线程全局变量共享

注意:如果共享局部变量使用下列方法失败

#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void *thread1_func(void *arg)
{
    int    n;    
    int lfp = *(int *)arg;
    for (n = 0; n < 30; n++) {
        sleep(1);
        printf("AAAAAAAAAA\n");
        printf("A lfp = %d\n",lfp);
    }
    pthread_exit(NULL);
    //return NULL;
}
void *thread2_func(void *arg)
{
    int n;
    int lfp = *(int *)arg;
    for (n = 0; n < 30; n++) {
        sleep(1);
        printf("BBBBBBBBBB\n");
        printf("A lfp = %d\n",lfp);
    }
    return NULL;
}
int main(int argc, char *argv[])
{
    pthread_t tid1, tid2;
    int lfp = 10;
    if (pthread_create(&tid1, NULL, thread1_func, &lfp) != 0) {
        perror("main: pthread_create thread_1 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_1 succeed!\n");
    }
    lfp = 15;
    if (pthread_create(&tid2, NULL, thread2_func, &lfp) != 0) {
        perror("main: pthread_create thread_2 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_2 succeed!\n");
    }
    if (pthread_join(tid1, NULL) != 0) {
        perror("main: pthread_join thread_1 failed");
    }
    if (pthread_join(tid2, NULL) != 0) {
        perror("main: pthread_join thread_2 failed");
    }
    printf("main is exiting.\n");
    return 0;
}

如果运行结果

在线程A中局部变量理想值应该为10,线程B中局部变量理想值才应该为15,实际中两个都为15

解决方法

专门为局部变量申请内存,或尽量不用局部变量,不要将局部变量地址传入线程

#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void *thread1_func(void *arg)
{
    int    n;    
    int lfp = *(int *)arg;
    for (n = 0; n < 30; n++) {
        sleep(1);
        printf("AAAAAAAAAA\n");
        printf("A lfp = %d\n",lfp);
    }
    free(arg);
    pthread_exit(NULL);
    //return NULL;
}
void *thread2_func(void *arg)
{
    int n;
    int lfp = *(int *)arg;
    for (n = 0; n < 30; n++) {
        sleep(1);
        printf("BBBBBBBBBB\n");
        printf("B lfp = %d\n",lfp);
    }
    free(arg);
    return NULL;
}
int main(int argc, char *argv[])
{
    pthread_t tid1, tid2;
    int lfp = 10;
    int *p = malloc(sizeof(int));
    *p = 10;
    if (pthread_create(&tid1, NULL, thread1_func, p) != 0) {
        perror("main: pthread_create thread_1 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_1 succeed!\n");
    }
    lfp = 15;
    if (pthread_create(&tid2, NULL, thread2_func, &lfp) != 0) {
        perror("main: pthread_create thread_2 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_2 succeed!\n");
    }
    if (pthread_join(tid1, NULL) != 0) {
        perror("main: pthread_join thread_1 failed");
    }
    if (pthread_join(tid2, NULL) != 0) {
        perror("main: pthread_join thread_2 failed");
    }
    printf("main is exiting.\n");
    return 0;
}

多线程打开文件共享

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int fd = -1;
void *thread1_func(void *arg)
{
    char buf[128] = {0};
    read(fd,buf,5);
    printf("thread1: buf = %s\n",buf);
    pthread_exit(NULL);
    //return NULL;
}
void *thread2_func(void *arg)
{
    char buf[128] = {0};
    read(fd,buf,5);
    printf("thread2: buf = %s\n",buf);
    return NULL;
}
int main(int argc, char *argv[])
{
    pthread_t tid1, tid2;
    fd = open("./lfp",O_RDWR);
    if(fd < 0){
        perror("open fail\n");
    }
    if (pthread_create(&tid1, NULL, thread1_func, NULL) != 0) {
        perror("main: pthread_create thread_1 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_1 succeed!\n");
    }
    lfp = 15;
    if (pthread_create(&tid2, NULL, thread2_func, NULL) != 0) {
        perror("main: pthread_create thread_2 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_2 succeed!\n");
    }
    if (pthread_join(tid1, NULL) != 0) {
        perror("main: pthread_join thread_1 failed");
    }
    if (pthread_join(tid2, NULL) != 0) {
        perror("main: pthread_join thread_2 failed");
    }
    printf("main is exiting.\n");
    return 0;
}

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int fd = -1;
void *thread1_func(void *arg)
{
    char buf[128] = {0};
    read(fd,buf,5);
    printf("thread1: buf = %s\n",buf);
    pthread_exit(NULL);
    //return NULL;
}
void *thread2_func(void *arg)
{
    fd = open("./lfp",O_RDWR);
    if(fd < 0){
        perror("open fail\n");
    }
    char buf[128] = {0};
    read(fd,buf,5);
    printf("thread2: buf = %s\n",buf);
    return NULL;
}
int main(int argc, char *argv[])
{
    pthread_t tid1, tid2;
    if (pthread_create(&tid1, NULL, thread1_func, NULL) != 0) {
        perror("main: pthread_create thread_1 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_1 succeed!\n");
    }
    if (pthread_create(&tid2, NULL, thread2_func, NULL) != 0) {
        perror("main: pthread_create thread_2 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_2 succeed!\n");
    }
    if (pthread_join(tid1, NULL) != 0) {
        perror("main: pthread_join thread_1 failed");
    }
    if (pthread_join(tid2, NULL) != 0) {
        perror("main: pthread_join thread_2 failed");
    }
    printf("main is exiting.\n");
    return 0;
}

多线程互斥锁

线程与进程的同步互斥比较

• 多线程共享同一个进程的地址空间

• 优点:

线程间很容易进行通信

通过全局变量实现数据共享和交换

• 缺点:

多个线程同时访问共享对象时需要引入同步和互斥机制

互斥锁

互斥锁主要用来保护临界资源

• 每个临界资源都由一个互斥锁来保护,任何时刻最多只能有一个线程能访问

该资源

• 使用规则:

线程必须先获得互斥锁才能访问临界资源,访问完资源后释放该锁。

如果无法获得锁,线程会阻塞直到获得锁为止

mutex函数

pthread_mutex_init
#include <pthread.h>
 int  pthread_mutex_init(pthread_mutex_t  *mutex,pthread_mutexattr_t *attr)

// 初始化互斥锁

函数参数

mutex:互斥锁

attr: 互斥锁属性 // NULL表示缺省属性

函数返回值

成功:0

出错:-1

Posix Mutex API

PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略

保证了资源分配的公平性。

PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞

争。

PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样保

证当不允许多次加锁时不出现最简单情况下的死锁。PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

pthread_mutex_unlockpthread_mutex_lock

#include <pthread.h>
 int  pthread_mutex_unlock(pthread_mutex_t *mutex)// 释放互斥锁

函数参数

mutex:互斥锁

函数返回值

成功:0

出错:-1

#include <pthread.h>
 int  pthread_mutex_lock(pthread_mutex_t *mutex)// 申请互斥锁

函数参数

mutex:互斥锁

函数返回值

成功:0

出错:-1

举例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
//#define _LOCK_
unsigned int value1,value2, count=0;
pthread_mutex_t  mutex;
void *function(void *arg);
int main(int argc,  char *argv[])
{
    pthread_t  a_thread;
    if (pthread_mutex_init(&mutex, NULL) < 0)                                                                                                                                                          
    {
        perror("fail to mutex_init");
        exit(-1);
    }
    if (pthread_create(&a_thread, NULL, function, NULL) < 0)
    {
        perror("fail to pthread_create");
        exit(-1);
    }
    while ( 1 )
    {
        count++;
//#ifdef  _LOCK_
 //       pthread_mutex_lock(&mutex);
//#endif
        value1 = count;
        value2 = count;
//#ifdef  _LOCK_
//       pthread_mutex_unlock(&mutex);
//#endif
    }
    return 0;
 }
void  *function(void *arg)
{
     while ( 1 )
     {
#ifdef _LOCK_
        pthread_mutex_lock(&mutex);
#endif           
        if (value1 != value2)  
        {
            printf("count=%d , value1=%d, value2=%d\n",  count, value1, value2);
            usleep(100000);
        }     
#ifdef _LOCK_
        pthread_mutex_unlock(&mutex);
#endif
     }
     return  NULL;
 }

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
//#define _LOCK_
unsigned int value1,value2, count=0;
pthread_mutex_t  mutex;
void *function(void *arg);
int main(int argc,  char *argv[])
{
    pthread_t  a_thread;
    if (pthread_mutex_init(&mutex, NULL) < 0)                                                                                                                                                          
    {
        perror("fail to mutex_init");
        exit(-1);
    }
    if (pthread_create(&a_thread, NULL, function, NULL) < 0)
    {
        perror("fail to pthread_create");
        exit(-1);
    }
    while ( 1 )
    {
        count++;
#ifdef  _LOCK_
        pthread_mutex_lock(&mutex);
#endif
        value1 = count;
        value2 = count;
#ifdef  _LOCK_
        pthread_mutex_unlock(&mutex);
#endif
    }
    return 0;
 }
void  *function(void *arg)
{
     while ( 1 )
     {
#ifdef _LOCK_
        pthread_mutex_lock(&mutex);
#endif           
        if (value1 != value2)  
        {
            printf("count=%d , value1=%d, value2=%d\n",  count, value1, value2);
            usleep(100000);
        }     
#ifdef _LOCK_
        pthread_mutex_unlock(&mutex);
#endif
     }
     return  NULL;
 }

条件变量

• 条件变量是利用线程间共享的全局变量进行同步的一种机制。

• 主要包括两个动作:

一个线程等待“条件变量的条件成立”而挂起;

另一个线程使“条件成立”(给出条件成立信号)并唤醒挂起线程。

• 为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。对条件的测试是在互斥锁(互斥)的保护下进行的。

条件变量创建和注销

#include <pthread.h>
 int  pthread_cond_destroy(pthread_cond_t *cond)

函数参数

cond:条件变量

函数返回值

成功:0

出错:返回错误码

#include <pthread.h>
 int  pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t   *cond_attr)

函数参数

cond:条件变量

attr :通常为NULL。默认值是 PTHREAD_ PROCESS_PRIVATE,即此条件变量被同一进程内的各个线程使用。

函数返回值

成功:0

出错:返回错误码

条件变量等待

#include <pthread.h>
int  pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t   *mutex)

函数参数

cond:条件变量

mutex :互斥锁

函数返回值

成功:0

出错:返回错误码

条件变量唤醒

#include <pthread.h>
 int  pthread_cond_signal(pthread_cond_t *cptr)
//按入队顺序唤醒其中一个
int  pthread_cond_broadcast(pthread_cond_t *cptr)
唤醒所有等待线程

函数参数

cond:条件变量

函数返回值

成功:0

出错:返回错误码

实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>   
#include <semaphore.h>
pthread_mutex_t mutex;//锁定标志 
pthread_cond_t cond;//唤醒条件变量
void *thread1_func(void *arg)
{
    int    n;    
    printf("enter t1\n");
    pthread_mutex_lock(&mutex);//锁定    
    printf("t1 lock mutex\n");
    for (n = 0; n < 3; n++) {
        sleep(1);
        printf("AAAAAAAAAA\n");
    }
    pthread_cond_signal(&cond);//唤醒单个线程
    printf("t1 signal cond to t2\n");    
    pthread_mutex_unlock(&mutex);//解锁
    printf("t1 unlock mutex\n");    
    pthread_exit(NULL);
    //return NULL;
}
void *thread2_func(void *arg)
{
    int n;
    printf("\t\tenter t2\n");
    pthread_mutex_lock(&mutex);//锁定, 阻塞前被锁上
    printf("\t\tt2 lock mutex and wait\n");    
    pthread_cond_wait(&cond,&mutex);
    printf("\t\tt2 wakeup\n");
    for (n = 0; n < 3; n++) {
        sleep(1);
        printf("\t\tBBBBBBBBBB\n");
    }
    pthread_mutex_unlock(&mutex);//解锁
    printf("\t\tt2 unlock mutex\n");    
    return NULL;
}
int main(int argc, char *argv[])
{
    pthread_t tid1, tid2;
    //生成互斥锁mutex,默认属性初始化
    pthread_mutex_init(&mutex,NULL);
    //生成一个唤醒变量,默认属性=?同一进程内的所有线程使用
    pthread_cond_init(&cond,NULL);
    if (pthread_create(&tid1, NULL, thread1_func, NULL) != 0) {
        perror("main: pthread_create thread_1 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_1 succeed!\n");
    }
    if (pthread_create(&tid2, NULL, thread2_func, NULL) != 0) {
        perror("main: pthread_create thread_2 failed");
        return 1;
    } else {
        printf("main: pthread_create thread_2 succeed!\n");
    }
    if (pthread_join(tid1, NULL) != 0) {
        perror("main: pthread_join thread_1 failed");
    }
    if (pthread_join(tid2, NULL) != 0) {
        perror("main: pthread_join thread_2 failed");
    }
    pthread_cond_destroy(&cond);//释放阻塞唤醒变量
    pthread_mutex_destroy(&mutex);//释放互斥锁mutex资源
    printf("main is exiting.\n");
    return 0;
}


目录
相关文章
|
8天前
|
并行计算 调度 UED
为什么要用多线程?
为什么要用多线程?
33 0
|
8月前
65.【 多线程2】(三)
65.【 多线程2】
30 0
|
8月前
65.【 多线程2】(二)
65.【 多线程2】
29 0
|
8天前
|
安全 Java C#
C#多线程详解
C#多线程详解
17 0
|
8天前
|
Unix Linux 编译器
c++多线程
c++多线程
25 0
|
8月前
65.【 多线程2】(四)
65.【 多线程2】
27 0
|
8天前
|
Java API 调度
多线程 02
多线程 02
17 0
|
8天前
|
C#
[C#] 多线程的使用
[C#] 多线程的使用
18 0
|
9月前
八 多线程
八 多线程
42 0
|
9月前
|
调度
多线程 简单了解使用
多线程 简单了解使用
41 0

热门文章

最新文章