分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. npm命令的使用

    本人实际项目开发前端用的是单页vue组件开发.不管是启动项目还是下载依赖,都要使用npm命令. 东凑凑,西拼拼,整理些常用的. 前提:需要下载node.js.这里就不详细说明了.具体参照官方文档. 1 ...

  2. node.js使用express模块创建web服务器应用

    1.安装express模块 在命令行输入 npm install body-parser --save npm install express --save 2.创建app.js文件 /*应用程序入口 ...

  3. iOS蓝牙4.0开发

    文/starfox寒流(简书作者)原文链接:http://www.jianshu.com/p/974d165f78b5著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. iOS 蓝牙4.0 ...

  4. python自动化测试—配置文件的使用

    一.什么是配置文件? 配置文件示例 [mysql] default-character-set = utf8 [mysqld] port = 3306 basedir = c:\mysql-5.7.2 ...

  5. jenkins 构建时显示git分支插件、显示构建分支插件

    参数化构建分支 1.安装插件:Git Parameter 2.找到我们在Jenkins中建立的工程,勾选“参数化构建过程”,并如下配置 3.在“源码管理”中如下配置 Jenkins构建完显示构建用户和 ...

  6. python _str_方法

    _str_方法: 使用:如: class Car: def __init__(self,newWheelNum,newColor): self.wheelNum=newWheelNum self.co ...

  7. robotframework 使用Chrome手机模拟器两种方法

    Open Google Simulator1 ${device metrics}= Create Dictionary width=${360} height=${640} pixelRatio=${ ...

  8. Python之常用模块三(面向对象相关的三个模块)

    hashlib.configparser.logging模块 一.常用模块二 hashlib模块 hashlib提供了常见的摘要算法,如md5和sha1等等. 那么什么是摘要算法呢?摘要算法又称为哈希 ...

  9. ESP8266--WIFI热点扫描

    现在,通常,为了让手机连上一个WiFi热点,基本上都是打开手机设置里面的WiFi设置功能,然后会看到里面有个WiFi热点列表,然后选择你要的连接上. 基本上你只要打开手机连接WiFi功能,都会发现附近 ...

  10. Vue全局混入

    混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式.混入对象可以包含任意组件选项.当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项. 数据对象合并 数据对象在 ...