分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种模式实现的更多相关文章

  1. SQL Server复制入门(二)----复制的几种模式

    简介 本系列文章的上一篇对复制是什么做了一个概述.本篇文章根据发布服务器,分发服务器和订阅服务器的组织方式和复制类型来讲述常用复制的几种模式. 模式的选择 选择复制的模式取决于多个方面.首先需要考虑具 ...

  2. SQL Server复制入门(二)----复制的几种模式 (转载)

    简介本系列文章的上一篇对复制是什么做了一个概述.本篇文章根据发布服务器,分发服务器和订阅服务器的组织方式和复制类型来讲述常用复制的几种模式. 模式的选择选择复制的模式取决于多个方面.首先需要考虑具体的 ...

  3. 2.1多线程(java学习笔记) java中多线程的实现(附静态代理模式)

    一.多线程 首先我们要清楚程序.进程.线程的关系. 首先进程从属于程序,线程从属于进程. 程序指计算机执行操作或任务的指令集合,是一个静态的概念. 但我们实际运行程序时,并发程序因为相互制约,具有“执 ...

  4. Java多线程学习(一)Java多线程入门

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79640870 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  5. JAVA实现多线程入门

    package com.thread;/** * 1:程序员可以在程序中执行多个线程,每一个线程完成一个功能,并于其他线程并发执行,这种 * 机制被称为多线程 * 2:实现线程的两种方法是,分别是继承 ...

  6. 【SSH系列】初识spring+入门demo

    学习过了hibernate,也就是冬天,经过一个冬天的冬眠,当春风吹绿大地,万物复苏,我们迎来了spring,在前面的一系列博文中,小编介绍hibernate的相关知识,接下来的博文中,小编将继续介绍 ...

  7. 基于springboot构建dubbo的入门demo

    之前记录了构建dubbo入门demo所需的环境以及基于普通maven项目构建dubbo的入门案例,今天记录在这些的基础上基于springboot来构建dubbo的入门demo:众所周知,springb ...

  8. apollo入门demo实战(二)

    1. apollo入门demo实战(二) 1.1. 下载demo 从下列地址下载官方脚本和官方代码 https://github.com/nobodyiam/apollo-build-scripts ...

  9. lua入门demo(HelloWorld+redis读取)

    1. lua入门demo 1.1. 入门之Hello World!! 由于我习惯用docker安装各种软件,这次的lua脚本也是运行在docker容器上 openresty是nginx+lua的各种模 ...

随机推荐

  1. 转载MySQL面试题

    1.MySQL的复制原理以及流程 (1).复制基本原理流程 主:binlog线程--记录下所有改变了数据库数据的语句,放进master上的binlog中: 从:io线程--在使用start slave ...

  2. js 学习一 猜数字游戏

    知识点 js 操作元素 增 (document.createElement(),document.body.appendChild()), 删(parentNode.removeChild()) ,改 ...

  3. 软件开发中oracle查询常用方法总结

    上次新霸哥和大家讲解了一些关于oracle的知识发现大家对oracle还是比较感兴趣的,下面新霸哥就大家比较关系的oracle中常用的查询有哪几种?做个和oracle相关的开发的朋友可能会知道答案,但 ...

  4. java.lang.IllegalStateException: No output folder

    将正在正常运行的tomcat打包(使用tar -zcvf命令打的包),然后放到其他服务器上使用非root用户解压(使用tar -zxvf命令)配置好之后,启动tomcat后报错如下 HTTP Stat ...

  5. 一、Core基于MVC的全局过滤器验证

    一.Core基于MVC的过滤器验证 1.添加一个过滤器.在Startup 中ConfigureServices方法里添加一个Filters 即我们自己授权代码类. public void Config ...

  6. keepalived的工作原理

    keepalived的工作原理 首先简单介绍一下vrrp协议 vrrp协议 用来实现路由器冗余的协议: Vrrp协议是为了消除在静态缺省路由环境下路由器单点故障引起的网络失效而设计的主备模式的协议,使 ...

  7. 遍历获取html页面所有元素的id

    因为要写一个权限管理系统精确到每个标签.以前用过的是给每个标签加权限判断的代码.但感觉这种方式太麻烦和落后,向让页面加载时自动把每个标签的id扫描到并保存到数据库.通过id控制.研究了下实现代码如下: ...

  8. 【转】在Linux下写一个简单的驱动程序

    转自:https://www.cnblogs.com/amanlikethis/p/4914510.html 本文首先描述了一个可以实际测试运行的驱动实例,然后由此去讨论Linux下驱动模板的要素,以 ...

  9. 安装php多进程模块pcntl

    在使用函数pcntl_fork()时报错  Fatal error: Uncaught Error: Call to undefined function pcntl_fork()....,原因是没有 ...

  10. Vue给子组件传值为空

    在项目中会遇到的情况.给子组件传值. 子组件页面可以把数据展现出来.可在方法中却获取不到 解决方法: 父组件添加判断,让页面执行完.再把值带过去.