C里提供了保证线程安全性的三种方法:

(添加头文件#include<pthread.h>,pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a, 在编译中要加 -lpthread参数)

  • 互斥锁

  通过锁的机制实现线程间的互斥,同一时刻只有一个线程可以锁定它,当一个锁被某个线程锁定的时候,如果有另外一个线程尝试锁定这个临界区(互斥体),则第二个线程会被阻塞,或者说被置于等待状态。只有当第一个线程释放了对临界区的锁定,第二个线程才能从阻塞状态恢复运行。

  int pthread_mutex_init(pthread_mutex_t* mutex, const thread_mutexattr_t* mutexattr);初始化一个互斥锁。

  int pthread_mutex_lock(pthread_mutex_t* mutex);如果mutex被锁定,当前进程处于等待状态;否则,本进程获得互斥锁并进入临界区。

  int pthread_mutex_trylock(pthread_mutex_t* mutex);和lock不同的时候,尝试获得互斥锁不成功不会使得进程进入阻塞状态,而是继续返回线程执行。该函数可以有效避免循环等待锁,如果trylock失败可以释放已经占有的资源,这样可以避免死锁。

  int pthread_mutex_unlock(pthread_mutex_t* mutex);释放互斥锁,并使得被阻塞的线程获得互斥锁并执行。

  int pthread_mutex_destroy(pthread_mutex_t* mutex);用来撤销互斥锁的资源。

pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL); void pthread1(void* arg){
pthread_mutex_lock(&mutex);
.....//临界区
pthread_mutex_unlock(&mutex);
} void pthread2(void* arg){
pthread_mutex_lock(&mutex);
.....//临界区
pthread_mutex_unlock(&mutex);
}
  • 读写锁

读写锁与互斥量类似,不过读写锁允许更高的并行性。适用于读的次数大于写的次数的数据结构。

一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。

读锁锁住,加读锁,可以;加写锁会被阻塞,但此时会阻塞后续的读锁请求,防止读锁长期占用无法进入写模式。写锁就是互斥锁。

int pthread_rwlock_init(pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr);初始化读写锁

int pthread_destroy(pthread_rwlock_t* rwlock);销毁读写锁

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_cond_init(pthread_cond_t* cond,const pthread_condattr_t* attr);初始化动态分配的条件变量;也可以直接用PTHREAD_INITIALIZER直接赋值给静态的条件变量

  int pthread_cond_destroy(pthread_cond_t* cond)撤销条件变量资源;

  int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);使用该函数使得等待条件变量为真。线程被条件变量cond阻塞。

  int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex,const struct timespec* tspr);与wait类似,只是经历tspr时间后,即使条件变量不满足,阻塞也被解除,返回错误码。

  int pthread_cond_signal(pthread_cond_t* cond);唤醒因为条件变量阻塞的线程。

  int pthread_cond_broadcast(pthread_cond_t* cond);唤醒等待该条件的所有线程。

  

pthread_cond_t cond;
pthread_mutex_t mutex;
int count=;
void pthread1(void* arg){
pthread_mutex_lock(&mutex);
while(count==)
pthread_cond_wait(&cond,&mutex);
count--;
pthread_mutex_unlock(&mutex);
}
void pthread2(void* arg){
pthread_mutex_lock(&mutex);
if(count==)
pthread_cond_signal(&cond);
count++;
pthread_mutex_unlock(&mutex);
}
  • 自旋锁

  互斥量阻塞线程的方式是使其进入睡眠,而自旋锁是让线程忙等,即不会使其睡眠,而是不断循判断自旋锁已经被解锁。

  适用于占用自旋锁时间比较短的情况。

  • 信号量

介绍一下POSIX(POSIX标准定义了操作系统应该为应用程序提供的接口标准,换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统(即使是来自另一个厂商)上编译执行。)的信号量机制,定义在头文件/usr/include/semaphore.h

1)初始化一个信号量:sem_init()

int sem_init(sem_t* sem,int pshared,unsigned int value);

pshared为0时表示该信号量只能在当前进程的线程间共享,否则可以进程间共享,value给出了信号量的初始值。

2)阻塞线程

sem_wait(sem_t* sem)直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少;sem_trywait(sem_t* sem)是wait的非阻塞版本,它直接将sem的值减一,相当于P操作。

3)增加信号量的值,唤醒线程

sem_post(sem_t* sem)会使已经被阻塞的线程其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。相当于V操作。

3)释放信号量资源

sem_destroy(sem_t* sem)用来释放信号量sem所占有的资源

pthread_mutex_t mutex;
sem_t full,empty; void producer(void* arg){
while(){
sem_wait(&empty);//need to produce. the the empty of resource need minus 1
pthread_mutex_lock(&mutex);
...//produce a resource
pthread_mutex_unlock(&mutex);
sem_post(&full); //have produced a resource, the the full of resource need add 1
}
}
void consumer(void* arg){
while(){
sem_wait(&full);
pthread_mutex_lock(&mutex);
...//consume a resource
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}

Linux下C的线程同步机制的更多相关文章

  1. linux学习笔记之线程同步机制

    一.基础知识. 1:线程同步机制:互斥量,读写锁,条件变量,自旋锁,屏障. 1,互斥量:每个进程访问被互斥量保护的资源时,都需要先对互斥量进行判断. 1)互斥量重要属性:进程共享属性,健壮属性,类型属 ...

  2. Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁

    相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...

  3. linux下将不同线程绑定到不同core和cpu上——pthread_setaffinity_np

    =============================================================== linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主 ...

  4. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

  5. 分析.Net里线程同步机制

    我 们知道并行编程模型两种:一种是基于消息式的,第二种是基于共享内存式的. 前段时间项目中遇到了第二种 使用多线程开发并行程序共享资源的问题 ,今天以实际案例出发对.net里的共享内存式的线程同步机制 ...

  6. 【总结】Java线程同步机制深刻阐述

    原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread ...

  7. ThreadLocal和线程同步机制对比

    共同点: ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题. 区别: 在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量. 这时该变量是多个线程共享的,使用同 ...

  8. Java多线程编程(4)--线程同步机制

    一.锁 1.锁的概念   线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题.锁 ...

  9. Linux下的MySQL主从同步

    网上一些关于Linux下的MySQL主从同步教程非常之多,有些很简单的配置却弄的非常复杂,有些根本无法配通,下面是我通过简单的配置完成的主从同步过程,大家可以参考,此文章更适用于新手. 一.测试环境: ...

随机推荐

  1. webpack3中文版使用参考文档--全面解析webpack.config.js

    Webpack目前官方发布的最新版本是3.1.0,相对于2.0的怎么本,在语法上没有变动,只是新增了功能.使用webpack,需要事先安装node.js,并对node.js生态有一些基本的了解,比如( ...

  2. VB6之截图

    今天先把主要逻辑写出来,如果有时间就实现一个真正的截图工具. Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC ...

  3. PHPOffice/PHPExcel生成省市区三级联动的excel表格

    最近公司需要用到一个省市区三级联动的excel表格,但是数据都在数据库,又太多,人工不好制作,就让我这个phper来帮忙啦. 主要用到的是excel的定义名称,数据验证.其中数据验证的列表只能是一列或 ...

  4. Oracle PIVOT 行转列方法

    数据库中業種的存储如下图: SELECT * FROM M_TORIHIKISAKI_GYOSYU 其中GYIUSYU_CD字段代表不同的業種 而画面需要实现下图所示样式:(将每条数据的業種横向展开显 ...

  5. 移动端em与rem区别

    rem与em都是相对单位,我们使用它们的目的就是为了适应各种手机屏幕. rem是根据html根节点来计算的,而em是继承父元素的字体.比如下面一个demo <!doctype html> ...

  6. MySQL IO线程及相关参数调优

    一.关于一个SQL的简单的工作过程 1.工作前提描述 1.启动MySQL,在内存中分配一个大空间innodb_buffer_pool(其中log_buffer) 2.多用户线程连接MySQL,从内存分 ...

  7. HTML中的行内元素和框元素详解

    定义 传统的块级元素定义中只是说明了在文档流中形成了一个块,在前后加换行,这里有些笼统. 其实框元素是指宏观上的框元素,它包括3种类型:1.本身就是块级元素 2.dispaly被设置为类block 3 ...

  8. Out of mind - 魔术纸

    魔术纸 显示屏与纸张的完美结合.类似电子墨水.柔性显示器.魔术纸柔软似真正的纸张.用魔术纸做成的电子书,控制器在书轴处. 每一页能显示不同的东西.一本书可以完全按页显示在电子书上.可以换一本书来显示. ...

  9. python数据结构链表之单向链表

    单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. 表元素域ele ...

  10. Java 9 揭秘(17. Reactive Streams)

    Tips 做一个终身学习的人. 在本章中,主要介绍以下内容: 什么是流(stream) 响应式流(Reactive Streams)的倡议是什么,以及规范和Java API 响应式流在JDK 中的AP ...