前言一、概念
1.1、什么是线程1.2、实现原理1.3、线程共享资源1.4、线程非共享资源1.5、线程优缺点 二、线程常用方法
2.1、pthread_self2.2、pthread_create2.3、pthread_exit2.4、pthread_join2.5、pthread_detach2.6、pthread_cancel 三、线程同步
3.1、概念 四、互斥量
4.1、基本概念4.2、常用函数
4.2.1 pthread_mutex_init4.2.2 pthread_mutex_destroy4.2.3 pthread_mutex_lock4.2.3 pthread_mutex_unlock 4.3、读写锁
4.3.1 状态4.3.2 特性4.3.3 案例4.4 条件变量 五、信号量
5.1、sem_init5.2、sem_destroy5.3、sem_wait5.4、sem_post
一、概念1.1、什么是线程类Unix系统中,早期是没有“线程”概念的,80年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。
线程(LWP)是 *** 作系统能够进行运算调度的最小单位,是轻量级的进程,其本质仍是进程;
线程是轻量级的进程,则线程与它的区别有哪些?
与进程相比,线程没有独立的地址空间(共享);
1.2、实现原理在Linux下,线程是最小的执行单位;进程是最小分配资源的单元(一个线程的进程);
1.3、线程共享资源进程与线程关系密切:
线程也有PCB,创建线程使用的底层函数和进程一样,都是clone;每个线程都有自己不同的PCB,但PCB中下指向内存资源的三级页表是相同的;进程可以蜕变成线程;线程可看做寄存器和栈的集合;
1.4、线程非共享资源文件描述符表;每种信号的处理方式;当前工作目录;用户ID和组ID;内存地址空间(.text/.data/.bss/heap/共享库);
1.5、线程优缺点线程ID;处理器线程和栈指针(内核栈);独立的栈空间(用户空间栈);errno变量;信号屏蔽字;
优点:
提高程序并发性;开销小;数据通信、共享数据方便;
缺点:
二、线程常用方法 2.1、pthread_self库函数,不稳定;调试困难;对信号支持不友好;
2.2、pthread_create
案例
#include#include #include using namespace std; void *test_func(void *arg){ cout << (int *)arg << "th I am 【" << pthread_self() << "】thread" << endl; return nullptr; } int main(int argc, char* argv[]) { pthread_t tid; int ret, i; for(i=0; i < 5; ++i){ if((ret = pthread_create(&tid, NULL, test_func, (void *)i)) != 0){ cout << "pthread error" << endl; exit(1); } } pthread_exit(NULL); }
2.3、pthread_exit
2.4、pthread_join
案例
#include#include #include using namespace std; typedef struct { std::string name; int age; }exit_t; void *func(void *){ exit_t *m_t = new exit_t; m_t->name = "xiaomi"; m_t->age = 15; cout << "I am thread..." << endl; pthread_exit((void *)m_t); } int main(int argc, char* argv[]) { pthread_t tid; exit_t *m_t; int ret; cout << "I am main..." << endl; if((ret = pthread_create(&tid, NULL, func, NULL)) != 0){ cout << "create error" << endl; exit(1); } pthread_join(tid, (void **)&m_t); cout << "name: 【" << m_t->name << "】" << " age:【" << m_t->age << "】" << endl; pthread_exit((void *)1); return 0; }
2.5、pthread_detach
案例
#include#include using namespace std; void *func(void *arg){ cout << "I am pthread" << endl; return (void *)1; } int main(int argc, char* argv[]) { pthread_t tid; pthread_create(&tid, NULL, func, NULL); cout << "I am main" << endl; int ret = pthread_detach(tid); cout << "detach pthread => " << ret << endl; return 0; }
2.6、pthread_cancel
案例
#include三、线程同步 3.1、概念#include #include using namespace std; void *func(void *arg){ while(1){ cout << "---------------" << endl; sleep(1); } pthread_testcancel(); } int main(int argc, char* argv[]) { pthread_t tid; pthread_create(&tid, NULL, func, NULL); cout << "I am main" << endl; sleep(3); pthread_cancel(tid); return 0; }
指一个线程发出某一个功能时,在没有得到结果之前,该调不返回。同时其他线程为保证数据一致性,不能调用该功能;
用于多个控制流,共同 *** 作一个共享资源的情况;
数据混乱原因
四、互斥量 4.1、基本概念资源共享;调度随机;线程间缺乏必要的同步机制;
4.2、常用函数 4.2.1 pthread_mutex_init每个线程在对资源 *** 作前都尝试先加锁,成功上锁才能 *** 作, *** 作结束后解锁,确保在于时间有关的 *** 作上不会出现错误;
4.2.2 pthread_mutex_destroy
4.2.3 pthread_mutex_lock
4.2.3 pthread_mutex_unlock
案例
#include4.3、读写锁 4.3.1 状态#include #include using namespace std; pthread_mutex_t mutex; void *func(void *arg){ while(1){ pthread_mutex_lock(&mutex); cout << "I am pthread" << endl; sleep(1); pthread_mutex_unlock(&mutex); sleep(2); } return (void *)1; } int main(int argc, char* argv[]) { pthread_t tid; pthread_mutex_init(&mutex, NULL); pthread_create(&tid, NULL, func, NULL); while(1){ pthread_mutex_lock(&mutex); cout << "I am main" << endl; sleep(1); pthread_mutex_unlock(&mutex); sleep(2); } pthread_join(tid, NULL); pthread_mutex_destroy(&mutex); return 0; }
4.3.2 特性读模式下加锁状态;写模式下加锁状态;不加锁状态;
4.3.3 案例写锁优先级别高;写独占,读共享;
#include4.4 条件变量#include #include using namespace std; int count; pthread_rwlock_t rwlock; void *r_func(void *arg){ while(1){ pthread_rwlock_wrlock(&rwlock); cout << "【read】 data = " << count << " thread_id: " << pthread_self() << endl; pthread_rwlock_unlock(&rwlock); sleep(1); } return nullptr; } void *w_func(void *arg){ while(1){ pthread_rwlock_wrlock(&rwlock); cout << "【write】 " << count++ << " thread_id: " << pthread_self() << endl; pthread_rwlock_unlock(&rwlock); sleep(1); } return nullptr; } int main(int argc, char* argv[]) { int i; pthread_t pid[8]; pthread_rwlock_init(&rwlock, NULL); for(i=0; i<3; ++i) pthread_create(&pid[i], NULL, w_func, NULL); for(i=0; i<5; ++i) pthread_create(&pid[i+3], NULL, r_func, NULL); for(i=0; i<8; ++i){ pthread_join(pid[i], NULL); } pthread_rwlock_destroy(&rwlock); return 0; }
本身不是锁,可造成线程阻塞。通常与互斥锁配合使用,给多线程提供一个会合场所;
pthread_cond_init
pthread_cond_destroy
pthread_cond_wait
pthread_cond_signal
pthread_cond_broadcast
案例
#include五、信号量#include #include #include using namespace std; vector vc; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;; void *product_func(void *arg){ while(1){ pthread_mutex_lock(&mutex); vc.push_back(rand() % 100); cout << "product 【" << vc[0] << "】" << endl; pthread_mutex_unlock(&mutex); pthread_cond_signal(&has_product); sleep(2); } return NULL; } void *comsump_func(void *arg){ while(1){ pthread_mutex_lock(&mutex); while(vc.empty()){ pthread_cond_wait(&has_product, &mutex); } cout << "comsump 【" << vc[0] << "】" << endl; vc.pop_back(); pthread_mutex_unlock(&mutex); sleep(2); } return NULL; } int main(int argc, char* argv[]) { pthread_t ptid, ctid; pthread_create(&ptid, NULL, product_func, NULL); pthread_create(&ctid, NULL, comsump_func, NULL); pthread_join(ptid, NULL); pthread_join(ctid, NULL); return 0; }
5.1、sem_init相当于进化版的互斥锁,既能保证同步,数据不混乱,又能提高线程并发;
5.2、sem_destroy
5.3、sem_wait
5.4、sem_post
案例
#include#include #include #include using namespace std; int queue[5]; sem_t blank_n, product_n; void *product_func(void *arg){ int i=0; while(1){ sem_wait(&blank_n); queue[i%5] = rand() & 100; cout << "produce " << queue[i%5] << endl; sem_post(&product_n); i++; sleep(2); } return NULL; } void *comsump_func(void *arg){ int i=0; while(1){ sem_wait(&product_n); cout << "consume " << queue[i%5] << endl; queue[i%5] = 0; sem_post(&blank_n); i++; sleep(2); } return NULL; } int main(int argc, char* argv[]) { pthread_t ptid, ctid; sem_init(&blank_n, 0, 5); sem_init(&product_n, 0, 0); pthread_create(&ptid, NULL, product_func, NULL); pthread_create(&ctid, NULL, comsump_func, NULL); pthread_join(ptid, NULL); pthread_join(ctid, NULL); sem_destroy(&blank_n); sem_destroy(&product_n); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)