【原创实现】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的各种模 ...
随机推荐
- 一个常用的通过curl发送HTTP请求的函数
function: function curl_get($url, $params) { return curl_http($url, $params, 'GET'); } function curl ...
- HTTPS加密原理与过程
HTTPS加密原理与过程 HTTP 超文本传输协议一种属于应用层的协议 缺点: 通信使用明文(不加密),内容可能会被窃听 不验证通信方的身份,因此有可能遭遇伪装 无法证明报文的完整性,所以有可能已遭篡 ...
- Python3 A*寻路算法实现
# -*- coding: utf-8 -*- import math import random import copy import time import sys import tkinter ...
- 自用|DDoS防御产品集合
这是笔者对国内外的DDoS云防御产品做的一个集合,之前存在自己的文档里很久了,现在修改后发出来大家可以一起看看,有需要的也方便比较按需选择.有免费版的我会放在前面,遇到微量攻击时可以应急,并且也可以感 ...
- [PyQt5]动态显示matplotlib作图(一)
完整实例 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QVBoxLayout, QSizePoli ...
- LDO ,开关电源DC-DC的优缺点
一般LDO电源自身的功耗为(Vin-Vout)*Iout,因此这两者越大,功耗也越大,效率也就越低. LDO ,开关电源DC-DC的优缺点(2008-11-06 22:40:23)转载标签: 电源杂谈 ...
- DP | Luogu P1466 集合 Subset Sums
题面:P1466 集合 Subset Sums 题解: dpsum=N*(N+1)/2;模型转化为求选若干个数,填满sum/2的空间的方案数,就是背包啦显然如果sum%2!=0是没有答案的,就特判掉F ...
- 清北学堂北京大学文宏宇神仙讲课day7
今天是最后一天 今天讲noip真题: ‘’ ‘’‘’ 课程终于还是上完了,收获比上一次多!
- deepin 常见快捷键及常用命令
常用命令 1)安装软件命令行:dpkg -i <.deb file name>示例:dpkg -i avg71flm_r28-1_i386.deb2)安装一个目录下面所有的软件包命令行:d ...
- big.js常用方法
官网api:http://mikemcl.github.io/big.js/ +:minus.minus(n) ⇒ Big %:mod.mod(n) ⇒ Big -:plus.plus(n) ⇒ B ...