线程同步指的是当一个线程在对某个临界资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作,其他线程才能操作,也就是协同步调,让线程按预定的先后次序进行运行。线程同步的方法有四种:互斥锁、信号量、条件变量、读写锁。

1.互斥锁

头文件及函数声明:

#include <pthread.h>
/*
mutex是锁,
attr是锁的属性,一般用不上,传个NULL默认属性就可以
*/
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);int pthread_mutex_destroy(pthread_mutex_t *mutex);

示例代码
以下代码在多线程并发中已经做过分析。我们这里直接进行修改。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>pthread_mutex_t mutex;//定义锁
int g = 0;void* pthread_fun(void* arg)
{for(int i = 0; i < 1000; i++){pthread_mutex_lock(&mutex);//上锁g++;printf("g = %d\n",g);pthread_mutex_unlock(&mutex);//解锁}pthread_exit(NULL);
}int main()
{pthread_mutex_init(&mutex, NULL);//初始化锁pthread_t id[5];for(int i = 0; i < 5; i++){pthread_create(&id[i],NULL,pthread_fun,NULL);}for(int j = 0; j < 5; j++){char* s = NULL;pthread_join(id[j],(void**)&s);}pthread_mutex_destroy(&mutex);//销毁锁exit(0);
}

运行结果最后输出都是5000,不会再出现低于5000的情况。

2 信号量

头文件及函数声明:

#include <semaphore.h>
/*
sem:信号对象。
pshared:指明信号量的类型。不为0时此信号量在进程间共享,为0时只能为当前进程的所有线程共享。
value:指定信号量值的大小。
*/
int sem_init(sem_t *sem, int pshared, unsigned int value);int sem_wait(sem_t *sem);//原子操作,P操作,将信号值减1int sem_post(sem_t *sem);//原子操作,V操作,将信号值加1int sem_destroy(sem_t *sem);//销毁信号量

示例代码:函数线程完成将用户输入的数据存储到文件中

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>
#include<semaphore.h>
#include<fcntl.h>sem_t sem1;
sem_t sem2;
char buff[128] = {0};void* pthread_fun(void* arg)
{int fd = open("sem.txt",O_WRONLY|O_CREAT,0664);assert(fd != -1);while(1){sem_wait(&sem2);if(strncmp(buff,"end",3) == 0){break;}write(fd,buff,strlen(buff));memset(buff,0,128);sem_post(&sem1);}sem_destroy(&sem1);sem_destroy(&sem2);pthread_exit(NULL);
}int main()
{sem_init(&sem1,0,1);sem_init(&sem2,0,0);pthread_t id;int res = pthread_create(&id,NULL,pthread_fun,NULL);assert(res == 0);while(1){printf("please input data:\n");sem_wait(&sem1);fgets(buff,128,stdin);buff[strlen(buff)-1] = '\0';sem_post(&sem2);if(strncmp(buff, "end", 3) == 0){break;}}char* s = NULL;pthread_join(id,(void**)s);exit(0);
}

3.条件变量

条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程。
头文件及函数声明:

#include <pthread.h>
/*
cond:
attr:
*/
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);int pthread_cond_signal(pthread_cond_t *cond); //唤醒单个线程int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒所有等待的线程int pthread_cond_destroy(pthread_cond_t *cond);

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>pthread_mutex_t mutex;
pthread_cond_t cond;
void * fun1( void * arg)
{char* s = ( char*)arg;while( 1 ){//阻塞,被唤醒pthread_mutex_lock(&mutex);pthread_cond_wait(&cond,&mutex);pthread_mutex_unlock(&mutex);printf("fun1 read:%s\n",s);if (strncmp(s,"end",3) == 0 ){break;}}
}void * fun2( void * arg)
{char* s = ( char*)arg;while( 1 ){//阻塞,被唤醒pthread_mutex_lock(&mutex);pthread_cond_wait(&cond,&mutex);pthread_mutex_unlock(&mutex);printf("fun2 read:%s\n",s);if ( strncmp(s,"end",3) == 0 ){break;}}
}int main()
{pthread_t id[2];char buff[128] = {0};pthread_cond_init(&cond,NULL);pthread_mutex_init(&mutex,NULL);pthread_create(&id[0],NULL,fun1,( void*)buff);pthread_create(&id[1],NULL,fun2,( void*)buff);while( 1 ){fgets(buff,128,stdin);if ( strncmp(buff,"end",3) == 0 ){pthread_mutex_lock(&mutex);pthread_cond_broadcast(&cond);pthread_mutex_unlock(&mutex);break;}else{pthread_mutex_lock(&mutex);pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);}}pthread_join(id[0],NULL);pthread_join(id[1],NULL);exit(0);
}

4.读写锁

头文件及函数声明:

#include <pthread.h>
/*
rwlock:指向读写锁的指针
attr:读写锁属性,一般传入NULL,使用默认属性
每一个函数执行成功就返回0,否则就返回一个错误码
*/
int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr);int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//都锁定int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//写锁定int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁读写锁int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//释放读写锁

Linux线程——线程同步相关推荐

  1. linux usleep 线程控制权_linux多线程同步—信号量

    linux多线程编程-信号量 信号量机制 锁机制使用是有限制的,锁只有两种状态,即加锁和解锁,对于互斥的访问一个全局变量,这样的方式还可以对付,但是要是对于其他的临界资源,比如说多台打印机等,这种方式 ...

  2. Linux c线程间的同步----互斥锁、条件变量、信号量

    线程 一个进程中的所有线程共享为进程分配的地址空间.所以进程地址空间中的代码段和数据段都是共享的. 如果定义一个函数在各个线程中都可以调用,定义一个全部变量,在各个线程中都可以访问到. 各线程共享资源 ...

  3. 50.Linux 线程三 同步

    Linux系统中常用实现线程同步的方式有三种,分别为互斥锁.条件变量与信号量. 下面将对这三种方式逐一进行讲解. 4.1 互斥锁 使用互斥锁实现线程同步时,系统会为共享资源添加一个称为互斥锁的标记,防 ...

  4. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  5. linux动态线程池--原理,这儿的代码不完整

    本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量.文章的最后,我们 ...

  6. linux c 线程的创建、线程等待、线程终止、线程分离

    1. 什么是线程   线程是进程执行内部的一个执行分支,在一个进程内部运行的多种执行流:内部本质上是多个线程在同一个地址空间运行:第一个pcb称之为主线程:有多个线程就有多个执行流:一个进程至少有一个 ...

  7. Linux编程---线程

    首先说一下线程的概念.事实上就是运行在进程的上下文环境中的一个运行流.普通进程仅仅有一条运行流,可是线程提供了多种运行的路径并行的局面. 同一时候,线程还分为核心级线程和用户级线程.主要差别在属于核内 ...

  8. Linux线程——线程创建和基本使用(多线程并发)

    1.线程的概念与实现方式 1.1 线程的概念 概念:线程是进程内部的一条执行序列或执行路径,一个进程可以包含多条线程.线程是进行资源调度和分配的基本单位 . (1)每个进程至少有一条执行路径,所以一个 ...

  9. Linux上线程开发API概要(线程)

    进程与线程       典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理 ...

  10. linux posix 线程池_linux多线程--POSIX Threads Programming

    linux多线程自己从接触很久也有不少实践,但总是觉得理解不够深刻,不够系统.借这篇文章试着再次系统学习一下linux多线程编程,理解编程的concept,细致看一下POSIX pthread API ...

最新文章

  1. 国赛来咯,全国大学生智能汽车竞赛百度赛道正式开启
  2. Java详解:作为一个码农终于把MySQL日记看懂了
  3. Liststring[] 如何去重
  4. 使用Spring Boot和Heroku在20分钟内完成Java的单点登录
  5. ActionBar(3):搜索条
  6. IEEE最新声明:华为员工不能参与审稿,但是还能继续提供赞助
  7. 自学python考哪些证书-学python需要考证吗?考证有什么好处?
  8. 计算机专业的具体能力和素质要求,浅谈中职计算机专业学生职业素养的要求
  9. Postman POST方式提交json数据,PHP接收
  10. 基于numpy科学计算库实现线性回归linear regression
  11. 网络爬虫(网络蜘蛛)之网页抓取
  12. 假设某台台式计算机的内存储器容量为128,假设某台计算机的内存储器容量为128MB,硬盘容量为10GB,硬盘的容量是内存容量的多少倍?...
  13. 最新《择善教育》C/C++黑客编程项目实战教程
  14. mvc2 mvc_迅捷的MVC
  15. 李呈祥:bilibili在湖仓一体查询加速上的实践与探索
  16. Android商城排版,android排版布局学习
  17. ubuntu中将usb串口设备名称固定
  18. 飞行的小鸟java程序_飞扬的小鸟 Java基础案例
  19. postman点击一次连续发送多个请求
  20. Android Home键、锁屏键监听

热门文章

  1. 【转】HashTable 和 HashMap的区别
  2. webbench源码解析
  3. 用Unity3D实现简单的井字棋小游戏
  4. Nessus扫描器的使用
  5. iOS之多线程的使用和优缺点比较
  6. Linux_09 Linux软件包管理 rpm与yum
  7. 【Tools】MarkDown教程(七)-Typora详细教程
  8. 【Linux系统编程】线程私有数据
  9. 【IT资讯】华为“鸿蒙”所涉及的微内核究竟是什么
  10. oracle10g的silent,Linux 静默(Silent) 安装Oracle 10g