多线程全局变量共享
注意:如果共享局部变量使用下列方法失败
#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; }