分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 > 3){
        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[100];
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(%4) "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(1);

        // 走CAS模式
        if(TC <= 3){
            int oldSize = beanListSize;
            int newSize = oldSize + 1;

            if(newSize >= BC){
                printf("\n[CasMode]%s: 队列已达最大长度,本次不加入,当前长度为:%d", params->threadName, beanListSize);
                sleep(1);
                //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 >= 10){
                printf("\n[BlockMode]%s: 队列已达最大长度,本次不加入,当前长度为:%d", params->threadName, beanListSize);
                sleep(1);
                //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 0;
}
/*
 ============================================================================
 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(5);

    while(TRUE){
        // 消费一次 休眠2秒
        sleep(2);

        // 走CAS模式
        if(TC <= 3){

            int oldSize = beanListSize;
            int newSize = oldSize - 1;

            if(newSize < 1){
                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=1; i<BC;i++){
                    Bean_t *bean = &beanList[i];
                    if(bean->no != 0){
                        bean->no = 0;
                        bean->msg = NULL;
                        break;
                    }
                }
            }
            else{
                printf("\n[CasMode]%s:CAS失败,进行下一轮尝试,当前长度为:%d", params->threadName, beanListSize);
            }
        }
        else{
            // 加锁
            pthread_mutex_lock(params->mutex);

            beanListSize --;

            if(beanListSize < 1){
                printf("\n[BlockMode]__%s: 消息已消费完,本次不能消费,当前长度为:%d", params->threadName, beanListSize);
                sleep(1);
                //continue;
                //释放锁
                pthread_mutex_unlock(params->mutex);
                break;
            }

            int i;
            for(i=1; i<100;i++){
                Bean_t *bean = &beanList[i];
                if(bean->no != 0){
                    bean->no = 0;
                    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 0;
}

 

运行结果:

CAS模式:

阻塞Block模式(头文件里TC改为3以上,如5):

 

逐行写的代码,收获不小。

这个适用于初学者,还是要在本地跑一跑。

祝好运。

posted on 2019-06-21 17:27  大辉_FFf  阅读(382)  评论(0编辑  收藏  举报