【原创实现】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 实现 微信好友 个性签名 并 制作 词云图
环境搭建: pip install itchat numpy wordcloud matplotlib jieba 先把上面的几个包安装完成,直接上代码 import itchat from itch ...
- Bootstrap4中栅格系统CSS中 col-sm-* col-md-* col-lg-*的意义以及当其同时具有col-xs-* col-sm-* col-md-* col-lg-*的含义
根据Bootstrap--Grid 中 col-sm-* col-md-* col-lg-* col-xl-*的意义: .col-sm-* 小屏幕 手机 (≥ 576px) .col-md-* 中等屏 ...
- The authenticity of host 'github.com (52.74.223.119)' can't be established.
出现这种错误的问题应考虑是否配置ssh,若没有配置,则进行相关配置 若配置后还出现这种问题,这是由于本地缺少一个文化夹.直接yes而不是y或是回车
- 2019-11-29-Roslyn-通过-Nuget-管理公司配置
title author date CreateTime categories Roslyn 通过 Nuget 管理公司配置 lindexi 2019-11-29 08:58:52 +0800 201 ...
- 网页图片失效自动替换图片地址js代码
当你网页中的图片失效之后它会显示你预先设定好的默认图片,而不是显示为一个大大的红叉叉. js脚本如下: <script language="javascript"> v ...
- 递归算法几个实例---C/C++
//1.斐波那契数列 int fibo(int n) { || n==) { ; } else { ) + fibo(n-); } } //2.阶乘 int fac(int n) { || n==) ...
- git 合并某个分支指定的文件
$ git checkout <another-branch> <path-to-file> [<one-more-file> ...] $ git status ...
- @ResponseStatus注解作用
@ResponseStatus注解有两种用法,一种是加载自定义异常类上,一种是加在目标方法中 这里我们说一下加在目标方法上的这种情况,注解中有两个参数,value属性设置异常的状态码,reaseon是 ...
- 原生ajax 请求
什么是ajax AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新. 这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新, ...
- Python---项目需求分析
一.软件工程 .软件工程:工程化方法解决软件问题 操作步骤 1.需求分析 前台:给基础用户使用的页面 后台:给操作者/admin等使用的页面系统 不是服务器前后台概念 2.小米前台 商品展示 商品详情 ...