linux 线程同步(二)
信号量
信号量是相互排斥锁的升级版把相互排斥锁中1变成了n。举个简单的样例:如果如今有10个人,有一部手机。这10个人都竞争来使用手机打电话这就是相互排斥锁。对于信号量,如今可能是有4部手机,这10个人都竞争来使用手机打电话。相比相互排斥锁信号量由1变成了4。信号量相也就是操作系统中pv操作,它广泛应用进程或者线程间的同步与相互排斥。
相关库函数介绍
#include <semaphore.h>//所需头文件
//初始化信号量sem初始化的时候能够指定信号量的初始值,以及能否够在多进程间共享value表示要信号量初始值,pshared表示是否再多进程之前共享。 0表示不在多进程间
共享,非0表示在多进程之间共享详细能够man sem_init
//成功返回0,出错返回-1
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem)//相当于p操作
int sem_try_wait(sem_t *sem)//相当于p操作。在信号量值大于0时都能将信号量的值减一,与上面sem_wait的差别是,在信号值小于0时
int sem_post(sem_t *sem)//相当于v操作
int sem_getvalue(sem_t *sem)//用于得到信号量的值
int sem_destory(sem_t *sem) //释放信号量
信号量实例:生产者消费值
#include<stdio.h>
#include<stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFSIZE 10
int buf[BUFSIZE];
sem_t consumer_sem,producer_sem;
void *consumer(void *arg)
{
int c=0;
while(1)
{
sem_wait(&consumer_sem);//開始消费consumer_sem值减一
printf("consumer %d: %d\n",c,buf[c]);//消费数据
c++;
c=c%BUFSIZE;
sleep(1);//睡眠1s
sem_post(&producer_sem);//producer_sem值加1
}
}
void *producer(void *arg)
{
int p=0;
while(1)
{
sem_wait(&producer_sem);//開始生产producer_sem值减一
buf[p]=rand() % 1000 + 1;//生产数据
printf("producer %d: %d\n",p,buf[p]);
p++;
p=p%BUFSIZE;
sem_post(&consumer_sem);//consumer_sem值加1 }
} int main()
{ sem_init(&consumer_sem,0,0);
sem_init(&producer_sem,0,BUFSIZE); pthread_t pid,cid;
pthread_create(&pid,NULL,producer,NULL);
pthread_create(&cid,NULL,consumer,NULL); pthread_join(pid, NULL);
pthread_join(cid, NULL);
sem_destroy(&consumer_sem);
sem_destroy(&producer_sem);
return 0; }
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
条件变量
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包含两个动作:一个线程等待"条件变量的条件成立"而挂起;还有一个线程使"条件成立"(给出条件成立信号)。
为了防止竞争,条件变量的使用总是和一个相互排斥锁结合在一起。
条件变量类型为 pthread_cond_t。
相关库函数简单介绍
#include<pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);//条件变量的资源释放
int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);//条件变量的初始化
#include<pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *mutex,
const struct timespec *abstime);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
//等待某个条件是否成立。对于timewait()函数除了等待以外。能够设置一个时长。
int pthread_cond_signal(pthread_cond_t *cond);//种情况是仅仅有一个线程收到后运行动作。 //活动线程仅仅须要唤醒第一个正在睡眠的线程。如果您仅仅对队列加入了一个工作作业。 那么仅仅须要唤醒一个工作程序线程(再唤醒其他线程是不礼貌的! )
int pthread_cond_broadcast(pthread_cond_t *cond);//通过广播的形式发给子线程消息。子线程竞争运行。
不管哪种等待方式,都必须和相互排斥锁结合,以防止多个线程同一时候请求pthread_cond_wait()(或pthread_cond_timedwait())的竞争条件,且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列曾经,mutex保持锁定状态。并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被又一次加锁,以与进入pthread_cond_wait()前的加锁动作相应。
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h> struct msg {
struct msg *next;
int num;
}; struct msg *head;
/* 条件变量 */
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *consumer(void *p)
{
struct msg *mp;
while(1)
{
pthread_mutex_lock(&lock);
/* pthread_cond_wait(&has_product, &lock);
* 1.堵塞等待has_product被唤醒。
* 2.释放相互排斥锁。 pthread_mutex_unlock(&lock)
* 3.当被唤醒时。解除堵塞,而且又一次去申请获得相互排斥锁 pthread_mutex_lock(&lock)
*/
while (head == NULL)
pthread_cond_wait(&has_product, &lock);//等待 mp = head;
head = mp->next;
pthread_mutex_unlock(&lock);
printf("Consume %d\n", mp->num);
free(mp);
sleep(rand() % 5);
}
} void *producer(void *p)
{
struct msg *mp;
while(1)
{
mp =(struct msg *)malloc(sizeof(struct msg));
mp->num = rand() % 1000 + 1;
printf("Produce %d\n", mp->num);
pthread_mutex_lock(&lock);
mp->next = head;
head = mp;
pthread_mutex_unlock(&lock);
/* pthread_cond_broadcast(&has_product) 唤醒等待队列上的全部线程*/
//发送信号,告诉消费者有产品了
pthread_cond_signal(&has_product);
sleep(rand() % 5);
}
} int main(int argc, char *argv[])
{
pthread_t pid, cid;
srand(time(NULL));
pthread_create(&pid, NULL, producer, NULL);
pthread_create(&cid, NULL, consumer, NULL);
pthread_join(pid, NULL);
pthread_join(cid, NULL);
return 0;
}
linux 线程同步(二)的更多相关文章
- 【转】 Linux 线程同步的三种方法
线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...
- linux线程同步(1)-互斥量
一.概述 互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...
- Linux线程同步之读写锁(rwlock)
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 和 ...
- linux线程(二)内存释放
linux线程有两种模式joinable和unjoinable. joinable线程:系统会保存线程资源(栈.ID.退出状态等)直到线程退出并且被其他线程join. unjoinable线程:系统会 ...
- Linux线程同步
1. 线程同步: 当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图.当某个线程可以修改变量,而其他线程也可以读取或者修改这个变量的时候,就需要对这些线程进行同步,以确保他们在访问变量 ...
- Linux 线程同步的三种方法(互斥锁、条件变量、信号量)
互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...
- Linux线程同步:条件变量
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...
- linux线程同步(5)-屏障
一.概述 barrier(屏障)与互斥量,读写锁,自旋锁不同,它不是用来保护临界区的.相反,它跟条 ...
- linux线程同步(3)-读写锁
一.概述 读写锁与互斥量的功能类似,对临界区的共享资源进行保护!互斥量一次只让一个线程进入临界区, ...
随机推荐
- Mysql--查询相关语句总结
一.查询各个部门的最高工资及姓名,其中薪资字段是字符串类型: 优化前: SELECT *FROM (SELECT a.`deptno`, a.`sal`, a.`ename` FROM emp a O ...
- mysql安装及navicat连接
1.下载mysql官方连接:https://dev.mysql.com/downloads/mysql/ 下载成功后,解压到自己想要的路径下并创建my.ini文件和配置环境变量 然后我们在根目录下创建 ...
- thinkphp5生成二维码
1.运用composer下载拓展到vendor下 composer require aferrandini/phpqrcode 2.common.php 里面写生成二维码函数 <?php // ...
- Hadoop2.x异常总结
问题1: 在执行bin/hdfs namenode -format格式化HDFS命令时,抛出异常,异常如下: 16/10/26 18:32:45 ERROR namenode.NameNode: Fa ...
- vue中的表单验证
http://www.cnblogs.com/luoxuemei/p/9295506.html /*是否合法IP地址*/ export function validateIP(rule, value, ...
- windows事件查看器
如果一个软件发生异常,软件本身没有提示异常信息, 需要从事件查看器中查看产生的错误事件 运行输入eventvwr或者win + X
- Jbox 弹出窗口 子页面操作完成后关闭 父页面刷新
父页面js //父页面js <script> var isFreshFlag = '1'; //添加会议活动 function addMeetingAct(){ var attendVip ...
- PAT顶级 1002. Business (35)
PAT顶级 1002. Business (35) As the manager of your company, you have to carefully consider, for each p ...
- linux-NMON监控
- 判断List集合为空
package org.springframework.util; CollectionUtils.isEmpty(list)