【原创实现】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的各种模 ...
随机推荐
- 093、如何用Graylog 管理日志? (2019-05-17 周五)
参考https://www.cnblogs.com/CloudMan6/p/7821817.html 上节我们已经部署好了 Graylog ,现在学习如何使用他来管理日志. 首先运行测试容器, ...
- JVM内存分配和垃圾回收以及性能调优
JVM内存分配策略 一:堆中优先分配Eden 大多数情况下,对象都在新生代的Eden区中分配内存.而新生代会频繁进行垃圾回收. 二:大对象直接进入老年代 需要大量连续空间的对象,如:长字符串.数组等, ...
- 关于&联系我
本文已迁移至: Github博客:https://coco5666.github.io/blog/about Gitee博客:https://coco56.gitee.io/blog/about 博客 ...
- 最简单的Android项目
这是我在windows环境下,试验过的最简单Android项目,只用记事本和命令行即可完成. 环境准备 开发环境需要Java SDK(官网下载),Android SDK(官网下载). 首先安装Java ...
- 第05课:GDB常用命令详解(中)
本科核心内容: info和thread命令 next.step.util.finish和return命令 5.1info和thread命令 在前面使用info break命令查看当前断点时介绍过,in ...
- 清楚webView的缓存
+(void)clearCache{ NSHTTPCookie *cookie; NSHTTPCookieStorage *storage = [NSHTTPCookieStorage s ...
- Java基本的程序结构设计 大数操作
大数操作 BigInteger 不可变的任意精度的整数.所有操作中,都以二进制补码形式表示 BigInteger(如 Java 的基本整数类型).BigInteger 提供所有 Java 的基本整数操 ...
- CentOS6.X系统启动流程
1.硬件启动阶段 BIOS自检 BIOS的功能由两部分组成,分别是POST码和Runtime服务.POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动.B ...
- safari兼容时间格式 NAN
问题: safari中不支持2018-08-01这种格式转为时间戳会显示NaN 方案: new Date('2018/08/01').getTime() 将-转化为/ // 正则替换 new Date ...
- python基础31[常用模块介绍]
python基础31[常用模块介绍] python除了关键字(keywords)和内置的类型和函数(builtins),更多的功能是通过libraries(即modules)来提供的. 常用的li ...