【原创实现】C 多线程入门Demo CAS Block 2种模式实现
分Cas和Block模式实现了demo, 供入门学习使用,代码全部是远程实现。
直接上代码:
- /*
- ============================================================================
- Name : Producer.c
- Author : qionghui.fang
- Version : 1.0
- Date : 2019年6月11日 下午2:32:30
- Copyright : Your copyright notice
- Description : Main
- ============================================================================
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <unistd.h>
- #include "header.h"
- int main(void) {
- printf("Start...\n");
- // 在阻塞模式下初始化信号量
- if(TC > ){
- pthread_mutex_init(&mutex_add,NULL);
- pthread_mutex_init(&mutex_take,NULL);
- }
- printf("Producer1 Thread init ...\n");
- pthread_t producer1;
- ThreadParam p1Params = {"Producer1", &mutex_add};
- pthread_create(&producer1, NULL, (void *)addBean, &p1Params);
- printf("Producer2 Thread init ...\n");
- pthread_t producer2;
- ThreadParam p2Params = { "Producer2", &mutex_add};
- pthread_create(&producer2, NULL, (void *)addBean, &p2Params);
- printf("Consumer1 Thread init ...\n");
- pthread_t consumer1;
- ThreadParam c1Params = { "Consumer1", &mutex_take};
- pthread_create(&consumer1, NULL, (void *)takeBean, &c1Params);
- printf("Consumer2 Thread init ...\n");
- pthread_t consumer2;
- ThreadParam c2Params = { "Consumer2", &mutex_take};
- pthread_create(&consumer2, NULL, (void *)takeBean, &c2Params);
- printf("Consumer3 Thread init ...\n");
- pthread_t consumer3;
- ThreadParam c3Params = { "Consumer3", &mutex_take};
- pthread_create(&consumer3, NULL, (void *)takeBean, &c3Params);
- pthread_join(producer1, NULL);
- printf("\n\nhere 1");
- pthread_join(producer2, NULL);
- printf("\nhere2");
- pthread_join(consumer1, NULL);
- pthread_join(consumer2, NULL);
- pthread_join(consumer3, NULL);
- printf("\n\nhere3");
- printf("\nEnd.");
- return EXIT_SUCCESS;
- }
- /*
- * header.h
- *
- * Created on: 2019年6月11日
- * Author: fangdahui
- */
- #include <pthread.h>
- #include <semaphore.h>
- #ifndef HEADER_H_
- #define HEADER_H_
- typedef int boolean;
- #define TRUE 1
- #define FALSE 0
- // 队列数量 BeanCount
- #define BC 10
- // thread count: <=3 为CAS模式 大于3为阻塞模式
- #define TC 3
- typedef struct bean{
- int no;
- char* msg;
- }Bean_t;
- typedef struct threadParam{
- char* threadName;
- pthread_mutex_t* mutex;
- }ThreadParam;
- // 队列
- Bean_t beanList[];
- volatile int beanListSize;
- // 原子操作 cmpxchg
- boolean cmpxchg(volatile int* dest, int compareValue, int newValue);
- // 加入元素
- void *addBean(ThreadParam* params);
- // 互斥信号
- pthread_mutex_t mutex_add;
- // 获取元素
- void *takeBean(ThreadParam* params);
- // 互斥信号
- pthread_mutex_t mutex_take;
- #endif /* HEADER_H_ */
- /*
- ============================================================================
- Name : Atom.c
- Author : qionghui.fang
- Version : 1.0
- Date : 2019年6月12日 上午8:53:35
- Copyright : Your copyright notice
- Description : CAS原子实现
- ============================================================================
- */
- #include "header.h"
- // Adding a lock prefix to an instruction on MP machine
- #define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "
- boolean cmpxchg(volatile int* dest, int compareValue, int newValue){
- // 暂存旧值
- int oldValue = *dest;
- // 默认多核
- boolean mp = TRUE;
- // 调用 cmpxchgl 指令
- __asm__ volatile (LOCK_IF_MP(%) "cmpxchgl %1,(%3)"
- : "=a" (newValue)
- : "r" (newValue), "a" (compareValue), "r" (dest), "r" (mp)
- : "cc", "memory");
- // 调用结束后 若地址目标值发生变更,则说明替换成功
- if(*dest != oldValue){
- return TRUE;
- }
- // 其它为失败
- return FALSE;
- }
- /*
- ============================================================================
- Name : Producer.c
- Author : qionghui.fang
- Version : 1.0
- Date : 2019年6月11日 下午2:32:30
- Copyright : Your copyright notice
- Description : 生产者
- ============================================================================
- */
- #include "header.h"
- #include <stdio.h>
- #include <unistd.h>
- #include <semaphore.h>
- void *addBean(ThreadParam * params){
- while(TRUE){
- // 生产1次 休眠1秒
- sleep();
- // 走CAS模式
- if(TC <= ){
- int oldSize = beanListSize;
- int newSize = oldSize + ;
- if(newSize >= BC){
- printf("\n[CasMode]%s: 队列已达最大长度,本次不加入,当前长度为:%d", params->threadName, beanListSize);
- sleep();
- //continue;
- break;
- }
- if(cmpxchg(&beanListSize, oldSize, newSize)){
- // 队列长度+1
- beanListSize = newSize;
- Bean_t bean = {beanListSize, "beanListSize"};
- beanList[beanListSize] = bean;
- printf("\n[CasMode]%s: CAS成功,当前长度为:%d", params->threadName, beanListSize);
- }
- else{
- printf("\n[CasMode]%s: CAS失败,进行下一轮尝试,当前长度为:%d", params->threadName, beanListSize);
- }
- }
- else{
- // 加锁
- pthread_mutex_lock(params->mutex);
- beanListSize ++;
- if(beanListSize >= ){
- printf("\n[BlockMode]%s: 队列已达最大长度,本次不加入,当前长度为:%d", params->threadName, beanListSize);
- sleep();
- //continue;
- //释放锁
- pthread_mutex_unlock(params->mutex);
- break;
- }
- Bean_t bean = {beanListSize, "beanListSize"};
- beanList[beanListSize] = bean;
- printf("\n[BlockMode]%s: 加锁成功,添加元素,当前长度为:%d", params->threadName, beanListSize);
- //释放锁
- pthread_mutex_unlock(params->mutex);
- }
- }
- printf("\n%s: 线程终止,当前长度为:%d\n", params->threadName, beanListSize);
- return ;
- }
- /*
- ============================================================================
- Name : Consumer.c
- Author : qionghui.fang
- Version : 1.0
- Date : 2019年6月21日 上午9:56:30
- Copyright : Your copyright notice
- Description : 消费者
- ============================================================================
- */
- #include "header.h"
- #include <stdio.h>
- #include <unistd.h>
- #include <semaphore.h>
- void *takeBean(ThreadParam* params){
- sleep();
- while(TRUE){
- // 消费一次 休眠2秒
- sleep();
- // 走CAS模式
- if(TC <= ){
- int oldSize = beanListSize;
- int newSize = oldSize - ;
- if(newSize < ){
- printf("\n[CasMode]%s: 消息已消费完,本次不能消费,当前长度为:%d", params->threadName, beanListSize);
- //continue;
- break;
- }
- if(cmpxchg(&beanListSize, oldSize, newSize)){
- // 队列长度-1
- beanListSize = newSize;
- printf("\n[CasMode]__%s: CAS成功,当前长度为:%d",params->threadName, beanListSize);
- int i;
- for(i=; i<BC;i++){
- Bean_t *bean = &beanList[i];
- if(bean->no != ){
- bean->no = ;
- bean->msg = NULL;
- break;
- }
- }
- }
- else{
- printf("\n[CasMode]%s:CAS失败,进行下一轮尝试,当前长度为:%d", params->threadName, beanListSize);
- }
- }
- else{
- // 加锁
- pthread_mutex_lock(params->mutex);
- beanListSize --;
- if(beanListSize < ){
- printf("\n[BlockMode]__%s: 消息已消费完,本次不能消费,当前长度为:%d", params->threadName, beanListSize);
- sleep();
- //continue;
- //释放锁
- pthread_mutex_unlock(params->mutex);
- break;
- }
- int i;
- for(i=; i<;i++){
- Bean_t *bean = &beanList[i];
- if(bean->no != ){
- bean->no = ;
- bean->msg = NULL;
- break;
- }
- }
- printf("\n[BlockMode]__%s: 加锁成功, 消费元素,当前长度为:%d", params->threadName, beanListSize);
- //释放锁
- pthread_mutex_unlock(params->mutex);
- }
- }
- printf("\n%s: 线程终止,当前长度为:%d\n", params->threadName, beanListSize);
- return ;
- }
运行结果:
CAS模式:
阻塞Block模式(头文件里TC改为3以上,如5):
逐行写的代码,收获不小。
这个适用于初学者,还是要在本地跑一跑。
祝好运。
【原创实现】C 多线程入门Demo CAS Block 2种模式实现的更多相关文章
- SQL Server复制入门(二)----复制的几种模式
简介 本系列文章的上一篇对复制是什么做了一个概述.本篇文章根据发布服务器,分发服务器和订阅服务器的组织方式和复制类型来讲述常用复制的几种模式. 模式的选择 选择复制的模式取决于多个方面.首先需要考虑具 ...
- SQL Server复制入门(二)----复制的几种模式 (转载)
简介本系列文章的上一篇对复制是什么做了一个概述.本篇文章根据发布服务器,分发服务器和订阅服务器的组织方式和复制类型来讲述常用复制的几种模式. 模式的选择选择复制的模式取决于多个方面.首先需要考虑具体的 ...
- 2.1多线程(java学习笔记) java中多线程的实现(附静态代理模式)
一.多线程 首先我们要清楚程序.进程.线程的关系. 首先进程从属于程序,线程从属于进程. 程序指计算机执行操作或任务的指令集合,是一个静态的概念. 但我们实际运行程序时,并发程序因为相互制约,具有“执 ...
- Java多线程学习(一)Java多线程入门
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79640870 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- JAVA实现多线程入门
package com.thread;/** * 1:程序员可以在程序中执行多个线程,每一个线程完成一个功能,并于其他线程并发执行,这种 * 机制被称为多线程 * 2:实现线程的两种方法是,分别是继承 ...
- 【SSH系列】初识spring+入门demo
学习过了hibernate,也就是冬天,经过一个冬天的冬眠,当春风吹绿大地,万物复苏,我们迎来了spring,在前面的一系列博文中,小编介绍hibernate的相关知识,接下来的博文中,小编将继续介绍 ...
- 基于springboot构建dubbo的入门demo
之前记录了构建dubbo入门demo所需的环境以及基于普通maven项目构建dubbo的入门案例,今天记录在这些的基础上基于springboot来构建dubbo的入门demo:众所周知,springb ...
- apollo入门demo实战(二)
1. apollo入门demo实战(二) 1.1. 下载demo 从下列地址下载官方脚本和官方代码 https://github.com/nobodyiam/apollo-build-scripts ...
- lua入门demo(HelloWorld+redis读取)
1. lua入门demo 1.1. 入门之Hello World!! 由于我习惯用docker安装各种软件,这次的lua脚本也是运行在docker容器上 openresty是nginx+lua的各种模 ...
随机推荐
- python 元类 MetaClass
type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ...
- 【微信小程序】图片压缩-纯质量压缩,非长宽裁剪压缩
原理:利用canvas来实现,将图片绘制到canvas上,然后canvas转图片时,微信提供的一个方法wx.canvasToTempFilePath(Object object, Object t ...
- Spring Boot任务(定时,异步,邮件)
一.定时任务 开启定时任务(在Spring Boot项目主程序上添加如下注解) @EnableScheduling //开启定时任务的注解 创建定时任务(创建一个Service如下) @Service ...
- AIX中文件系统管理
1.文件系统类型 AIX主要支持的文件系统有: JFS(Journaled File Systems) 日志型文件系统 JFS2(Enhanced Journaled File S ...
- Git 查看远端仓库地址
git remote -v
- yum 安装mysql-server 5.6
# rpm ivh http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm # yum install -y mysql-s ...
- tensorflow中张量_常量_变量_占位符
1.tensor 在tensorflow中,数据是被封装在tensor对象中的.tensor是张量的意思,即包含从0到任意维度的张量.常数是0维度的张量,向量是1维度的张量,矩阵是二维度的张量,以及还 ...
- @ResponseBody 注解是什么意思?
1. @ResponseBody注解的作用是将Controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据 ...
- Mac 升级python2.7 到 3.5
Mac 系统 OSX 10.12 以上 第1步:下载Python3.5 下载地址如下: Python3.5 第二步:安装python 3.50 点击下载好的pkg文件进行安装,安装完成之后,pyt ...
- Puppet利用Nginx多端口实现负载均衡
随着公司应用需求的增加,需要不断的扩展,服务器数量也随之增加,当服务器数量不断增加,我们会发现一台puppetmaster压力大,解析缓慢,而且时不时出现"time out"之类的 ...