生产者消费者, 哲学家问题, 线程池

生产者消费者

生产者消费者共享缓冲区,生产者向缓冲区中放数据,消费者从缓冲取中取数据,当缓冲区中被放满时,生产者进程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲取中没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。

1.信号量实现生产者消费者:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <semaphore.h>

#define NUM 5

int queue[NUM];
sem_t blank_number, product_number;

void *producer(void *arg) {
    int i = 0;
    int n = 10;
    while (n--) {
        sem_wait(&blank_number);
        queue[i] = rand() % 1000 + 1;
        printf("produce--%d\n", queue[i]);
        sem_post(&product_number);

        i = (i+1) % NUM;
        sleep(rand() % 1);
    }
    return NULL;
}

void *consumer(void *arg) {
    int i = 0;
    int n = 10;
    while (n--) {
        sem_wait(&product_number);
        printf("consumer--%d\n", queue[i]);
        queue[i] = 0;
        sem_post(&blank_number);

        i = (i + 1) % NUM;
        sleep(rand() % 3);
    }
    return NULL;
}

int main() {
    pthread_t pid, cid;

    sem_init(&blank_number, 0, NUM);
    sem_init(&product_number, 0, 0);

    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);

    pthread_join(pid, NULL);
    pthread_join(cid, NULL);

    sem_destroy(&blank_number);
    sem_destroy(&product_number);

    return 0;
}

2.条件变量实现生产者消费者:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>

#define CAPACITY 10

void err_thread(int ret, char *str) {
    if (ret != 0) {
        fprintf(stderr, "%s:%s\n", str, strerror(ret));
        pthread_exit(NULL);
    }
}

struct msg {
    int num;
    struct msg *next;
};

struct msg *head;
int size;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t has_data = PTHREAD_COND_INITIALIZER;

void *producer(void *arg) {
    struct msg *mp = malloc(sizeof(struct msg));
    int n = 10;
    while (n--) {
        mp->num = rand() % 1000 + 1;

        while (size >= CAPACITY) { // 缓冲区满了
            printf("size >= CAPACITY缓冲区满了\n");
            sleep(rand() % 3);
        }

        pthread_mutex_lock(&mutex);

        mp->next = head;
        head = mp;

        size++;

        pthread_mutex_unlock(&mutex);

        printf("--produce id =%lu produce %d size=%d\n", pthread_self(), mp->num, size);
        pthread_cond_signal(&has_data); // 将阻塞在该条件变量上的一个线程唤醒
        sleep(rand() % 3);
    }
    return NULL;
}

void *consumer(void *arg) {
    struct msg *mp;
    pthread_mutex_lock(&mutex); // 加锁
    int n = 10;
    while (n--) {
        while (head == NULL) { // 注意要用while
            pthread_cond_wait(&has_data, &mutex); //  阻塞等待条件变量, 判断条件是否满足
        }

        mp = head;
        head = mp->next;
        size--;
        pthread_mutex_unlock(&mutex);

        printf("--consume id: %lu, :%d size=%d\n", pthread_self(), mp->num, size);
        sleep(rand() % 3);
    }

    return NULL;
}

int main() {
    pthread_t pid[3], cid[3];
    int ret;
    srand(time(NULL));

    for (int i = 0; i < 10; ++i) {
        ret = pthread_create(&pid[i], NULL, producer, NULL);
        if (ret != 0) {
            err_thread(ret, "pthread_create producer error");
        }
    }

    for (int i = 0; i < 3; ++i) {
        ret = pthread_create(&cid[i], NULL, consumer, NULL);
        if (ret != 0) {
            err_thread(ret, "pthread_create consumer error");
        }
    }

    for (int i = 0; i < 3; ++i) {
        pthread_join(pid[i], NULL);
        pthread_join(cid[i], NULL);
    }
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&has_data);

    return 0;
}

哲学家问题

有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。哲学家有2个状态,思考或者拿起筷子吃饭。如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。
哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及死锁问题。

可能导致的死锁问题:

如果5个哲学家都去拿他左边的筷子, 再拿右边的筷子, 会导致每个人都在等待筷子, 导致死锁问题.

解决办法1:

最多允许4个哲学家吃饭, 第5个人想要拿筷子, 要阻塞直到有1个哲学家吃完, 释放筷子.
那怎么让第5个线程想要拿筷子前, 阻塞住?

用信号量机制, 信号量初始化为4, 每个线程拿筷子前调用sem_wait(), 吃完后, 调用sem_post(), 这样在第5个线程要拿筷子时, 就会阻塞, 直到有一个线程吃完后才会解除阻塞, 从而避免了死锁.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define NUM 4
/**
 * 最多允许4个哲学家吃饭, 第5个想吃要阻塞直到有1个哲学家吃完
 */
pthread_mutex_t chops[5];
sem_t max_philosopher_num;

void think(int i) {
    printf("I am thinking %d\n", i);
    sleep(rand() % 3);
}

void hungry(int i) {
    printf("I am hungry %d\n", i);
    sleep(rand() % 3);
}

void eat(int i) {
    printf("I am eating %d\n", i);
    sleep(rand() % 3);
}

void *philosopher(void *arg) {
    int i = (int) arg;
    think(i);
    hungry(i);

    sem_wait(&max_philosopher_num);
    pthread_mutex_lock(&chops[i]);
    pthread_mutex_lock(&chops[(i + 1) % 5]);

    eat(i);

    pthread_mutex_unlock(&chops[i]);
    pthread_mutex_unlock(&chops[(i + 1) % 5]);
    sem_post(&max_philosopher_num);

    return NULL;
}

int main() {
    pthread_t tid[5];
    srand(time(NULL));

    for (int i = 0; i < 5; ++i) {
        pthread_mutex_init(&chops[i], NULL);
    }
    sem_init(&max_philosopher_num, 0, NUM);

    for (int i = 0; i < 5; ++i) {
        pthread_create(&tid[i], NULL, philosopher, (void *) i);
    }

    for (int i = 0; i < 5; ++i) {
        pthread_join(tid[i], NULL);
    }
    for (int i = 0; i < 5; ++i) {
        pthread_mutex_destroy(&chops[i]);
    }

    sem_destroy(&max_philosopher_num);
    return 0;
}

解决办法2:

如果想给某个哲学家筷子,就将他需要的所有筷子都给他,然后让他进餐,否则就一个都不给他。从而避免了死锁。
怎么实现呢?
搞一个全局互斥量, 然后在某个线程拿筷子前, 先去拿到这个全局互斥量, 然后在拿他所需要的2个筷子, 因为别的线程没有抢到这个互斥量, 所以不能拿筷子, 而在这个互斥量这里阻塞.
所以这个拿到互斥量的线程可以拿到所有的筷子进餐, 在进餐结束后释放这个互斥量即可.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

/**
 * 如果想给某个哲学家筷子,就将他需要的所有资源都给他,然后让他进餐,否则就一个都不给他。
 */

pthread_mutex_t mutex, chops[5];

void think(int i) {
    printf("I am thinking %d\n", i);
    sleep(rand() % 3);
}

void hungry(int i) {
    printf("I am hungry %d\n", i);
    sleep(rand() % 3);
}

void eat(int i) {
    printf("I am eating %d\n", i);
    sleep(rand() % 3);
}

void *philosopher(void *arg) {
    int i = (int)arg;

    think(i);
    hungry(i);

    pthread_mutex_lock(&mutex); // 阻止其他线程拿筷子
    pthread_mutex_lock(&chops[i]);
    pthread_mutex_lock(&chops[(i + 1) % 5]);
    pthread_mutex_unlock(&mutex);

    eat(i);

    pthread_mutex_unlock(&chops[i]);
    pthread_mutex_unlock(&chops[(i + 1) % 5]);
    return NULL;
}

int main() {
    pthread_t tid[5];
    srand(time(NULL));

    pthread_mutex_init(&mutex, NULL);
    for (int i = 0; i < 5; ++i) {
        pthread_mutex_init(&chops[i], NULL);
    }

    for (int i = 0; i < 5; ++i) {
        pthread_create(&tid[i], NULL, philosopher, (void *)i);
    }

    for (int i = 0; i < 5; ++i) {
        pthread_join(tid[i], NULL);
    }

    pthread_mutex_destroy(&mutex);
    for (int i = 0; i < 5; ++i) {
        pthread_mutex_destroy(&chops[i]);
    }

    return 0;
}

解决办法3:

让奇数号哲学家先去拿他左边的筷子, 然后再拿他右边的筷子, 偶数号哲学家相反, 这样可以保证至少有一个哲学家可以拿到2个筷子进餐然后再释放2个筷子.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t chops[5];

void think(int i) {
    printf("I am thinking %d\n", i);
    sleep(rand() % 3);
}

void hungry(int i) {
    printf("I am hungry %d\n", i);
    sleep(rand() % 3);
}

void eat(int i) {
    printf("I am eating %d\n", i);
    sleep(rand() % 3);
}

void *philosopher(void *arg) {
    int i = (int)arg;

    think(i);
    hungry(i);

    if (i % 2 == 0) {
        pthread_mutex_lock(&chops[(i + 1) % 5]);
        pthread_mutex_lock(&chops[i]);
        eat(i);
        pthread_mutex_unlock(&chops[i]);
        pthread_mutex_unlock(&chops[(i + 1) % 5]);
    } else {
        pthread_mutex_lock(&chops[i]);
        pthread_mutex_lock(&chops[(i + 1) % 5]);
        eat(i);
        pthread_mutex_unlock(&chops[i]);
        pthread_mutex_unlock(&chops[(i + 1) % 5]);
    }

    return NULL;
}

int main() {
    pthread_t tid[5];
    srand(time(NULL));

    for (int i = 0; i < 5; ++i) {
        pthread_mutex_init(&chops[i], NULL);
    }

    for (int i = 0; i < 5; ++i) {
        pthread_create(&tid[i], NULL, philosopher, (void *)i);
    }

    for (int i = 0; i < 5; ++i) {
        pthread_join(tid[i], NULL);
    }

    for (int i = 0; i < 5; ++i) {
        pthread_mutex_destroy(&chops[i]);
    }

    return 0;
}

线程池

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
//#include "threadpool.h"

#define DEFAULT_TIME 10                 /*10s检测一次*/
#define MIN_WAIT_TASK_NUM 10            /*如果queue_size > MIN_WAIT_TASK_NUM 添加新的线程到线程池*/
#define DEFAULT_THREAD_VARY 10          /*每次创建和销毁线程的个数*/
#define true 1
#define false 0

typedef struct {
    void *(*function)(void *); // 函数指针, 回调函数
    void *arg; // 上面函数的参数
} threadpool_task_t; // 各子线程任务结构体

// 描述线程池相关信息
typedef struct threadpoll_t {
    pthread_mutex_t lock; /* 用于锁住本结构体 */
    pthread_mutex_t thread_counter; /* 记录忙状态线程个数de琐 -- busy_thr_num */

    pthread_cond_t queue_not_full; /* 当任务队列满时,添加任务的线程阻塞,等待此条件变量 */
    pthread_cond_t queue_not_empty; /* 任务队列里不为空时,通知等待任务的线程 */

    pthread_t *threads; // 存放线程池中每个线程的tid
    pthread_t adjust_tid; // 存管理线程tid
    threadpool_task_t *task_queue; // 任务队列(数组首地址)

    int min_thr_num;
    int max_thr_num;
    int live_thr_num;
    int busy_thr_num;
    int wait_exit_thr_num; // 要销毁的线程个数

    int queue_front;
    int queue_rear;
    int queue_size; // 队列中实际任务数
    int queue_max_size; // 队列容量

    int shutdown;
} threadpool_t;

void *threadpool_thread(void *threadpool);

void *adjust_thread(void *threadpool);

int is_thread_alive(pthread_t tid);

int threadpool_free(threadpool_t *pool);


threadpool_t *threadpoll_create(int min_thr_num, int max_thr_num, int queue_max_size) {
    int i;
    threadpool_t *pool = NULL;

    do {
        if ((pool = (threadpool_t *) malloc(sizeof(threadpool_t))) == NULL) {
            printf("malloc threadpoll fail");
            break;
        }

        pool->min_thr_num = min_thr_num;
        pool->max_thr_num = max_thr_num;
        pool->busy_thr_num = 0;
        pool->live_thr_num = min_thr_num;
        pool->wait_exit_thr_num = 0;
        pool->queue_size = 0;
        pool->queue_max_size = queue_max_size;
        pool->queue_front = 0;
        pool->queue_rear = 0;
        pool->shutdown = false;

        pool->threads = (pthread_t *) malloc(sizeof(pthread_t) * max_thr_num);
        if (pool->threads == NULL) {
            printf("malloc threads fail");
            break;
        }

        memset(pool->threads, 0, sizeof(pthread_t) * max_thr_num);

        /* 给 任务队列 开辟空间 */
        pool->task_queue = (threadpool_task_t *) malloc(sizeof(threadpool_task_t) * queue_max_size);
        if (pool->task_queue == NULL) {
            printf("malloc task_queue fail");
            break;
        }

        /* 初始化互斥琐、条件变量 */
        if (pthread_mutex_init(&(pool->lock), NULL) != 0
            || pthread_mutex_init(&(pool->thread_counter), NULL) != 0
            || pthread_cond_init(&(pool->queue_not_empty), NULL) != 0
            || pthread_cond_init(&(pool->queue_not_full), NULL) != 0) {
            printf("init the lock or cond fail");
            break;
        }

        /* 启动 min_thr_num 个 work thread */
        for (i = 0; i < min_thr_num; i++) {
            pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *) pool);   /*pool指向当前线程池*/
            printf("start thread 0x%x...\n", (unsigned int) pool->threads[i]);
        }
        pthread_create(&(pool->adjust_tid), NULL, adjust_thread, (void *) pool);     /* 创建管理者线程 */

        return pool;
    } while (0);

    threadpool_free(pool);      /* 前面代码调用失败时,释放poll存储空间 */

    return NULL;
}

void *threadpool_thread(void *threadpool) {
    threadpool_t *pool = (threadpool_t *) threadpool;
    threadpool_task_t task;

    while (true) {
        /* Lock must be taken to wait on conditional variable */
        /*刚创建出线程,等待任务队列里有任务,否则阻塞等待任务队列里有任务后再唤醒接收任务*/
        pthread_mutex_lock(&(pool->lock));

        /*queue_size == 0 说明没有任务,调 wait 阻塞在条件变量上, 若有任务,跳过该while*/
        while ((pool->queue_size == 0) && (!pool->shutdown)) {
            printf("thread 0x%x is waiting\n", (unsigned int) pthread_self());
            pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));

            /*清除指定数目的空闲线程,如果要结束的线程个数大于0,结束线程*/
            if (pool->wait_exit_thr_num > 0) {
                pool->wait_exit_thr_num--;

                /*如果线程池里线程个数大于最小值时可以结束当前线程*/
                if (pool->live_thr_num > pool->min_thr_num) {
                    printf("thread 0x%x is exiting\n", (unsigned int) pthread_self());
                    pool->live_thr_num--;
                    pthread_mutex_unlock(&(pool->lock));

                    pthread_exit(NULL);
                }
            }
        }

        /*如果指定了true,要关闭线程池里的每个线程,自行退出处理---销毁线程池*/
        if (pool->shutdown) {
            pthread_mutex_unlock(&(pool->lock));
            printf("thread 0x%x is exiting\n", (unsigned int) pthread_self());
            pthread_detach(pthread_self());
            pthread_exit(NULL);     /* 线程自行结束 */
        }

        /*从任务队列里获取任务, 是一个出队操作*/
        task.function = pool->task_queue[pool->queue_front].function;
        task.arg = pool->task_queue[pool->queue_front].arg;

        pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size;       /* 出队,模拟环形队列 */
        pool->queue_size--;

        /*通知可以有新的任务添加进来*/
        pthread_cond_signal(&(pool->queue_not_full));

        /*任务取出后,立即将 线程池琐 释放*/
        pthread_mutex_unlock(&(pool->lock));

        /*执行任务*/
        printf("thread 0x%x start working\n", (unsigned int) pthread_self());
        pthread_mutex_lock(&(pool->thread_counter));                            /*忙状态线程数变量琐*/
        pool->busy_thr_num++;                                                   /*忙状态线程数+1*/
        pthread_mutex_unlock(&(pool->thread_counter));

        (*(task.function))(task.arg);                          /*执行回调函数任务*/
        //task.function(task.arg);                                              /*执行回调函数任务*/

        /*任务结束处理*/
        printf("thread 0x%x end working\n", (unsigned int) pthread_self());
        pthread_mutex_lock(&(pool->thread_counter));
        pool->busy_thr_num--;                                       /*处理掉一个任务,忙状态数线程数-1*/
        pthread_mutex_unlock(&(pool->thread_counter));
    }

    pthread_exit(NULL);
}

/* 管理线程 */
void *adjust_thread(void *threadpool) {
    int i;
    threadpool_t *pool = (threadpool_t *) threadpool;
    while (!pool->shutdown) {
        sleep(DEFAULT_TIME);

        pthread_mutex_lock(&pool->lock);
        int queue_size = pool->queue_size;
        int live_thr_num = pool->live_thr_num;
        pthread_mutex_unlock(&pool->lock);

        pthread_mutex_lock(&pool->thread_counter);
        int busy_thr_num = pool->busy_thr_num;
        pthread_mutex_unlock(&pool->thread_counter);

        /* 创建新线程 算法: 任务数大于最小线程池个数, 且存活的线程数少于最大线程个数时 如:30>=10 && 40<100*/
        if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num) {
            pthread_mutex_lock(&(pool->lock));
            int add = 0;

            /*一次增加 DEFAULT_THREAD 个线程*/
            for (i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY
                        && pool->live_thr_num < pool->max_thr_num; i++) {
                if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i])) {
                    pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *) pool);
                    add++;
                    pool->live_thr_num++;
                }
            }

            pthread_mutex_unlock(&(pool->lock));
        }

        /* 销毁多余的空闲线程 算法:忙线程X2 小于 存活的线程数 且 存活的线程数 大于 最小线程数时*/
        if ((busy_thr_num * 2) < live_thr_num && live_thr_num > pool->min_thr_num) {

            /* 一次销毁DEFAULT_THREAD个线程, 随机10个即可 */
            pthread_mutex_lock(&(pool->lock));
            pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;      /* 要销毁的线程数 设置为10 */
            pthread_mutex_unlock(&(pool->lock));

            for (i = 0; i < DEFAULT_THREAD_VARY; i++) {
                /* 通知处在空闲状态的线程, 他们会自行终止*/
                pthread_cond_signal(&(pool->queue_not_empty));
            }
        }
    }

    return NULL;
}

int threadpool_destroy(threadpool_t *pool) {
    int i;
    if (pool == NULL) {
        return -1;
    }
    pool->shutdown = true;

    /*先销毁管理线程*/
    pthread_join(pool->adjust_tid, NULL);

    for (i = 0; i < pool->live_thr_num; i++) {
        /*通知所有的空闲线程*/
        pthread_cond_broadcast(&(pool->queue_not_empty));
    }
    for (i = 0; i < pool->live_thr_num; i++) {
        pthread_join(pool->threads[i], NULL);
    }
    threadpool_free(pool);

    return 0;
}

int threadpool_free(threadpool_t *pool) {
    if (pool == NULL) {
        return -1;
    }

    if (pool->task_queue) {
        free(pool->task_queue);
    }
    if (pool->threads) {
        free(pool->threads);
        pthread_mutex_lock(&(pool->lock));
        pthread_mutex_destroy(&(pool->lock));
        pthread_mutex_lock(&(pool->thread_counter));
        pthread_mutex_destroy(&(pool->thread_counter));
        pthread_cond_destroy(&(pool->queue_not_empty));
        pthread_cond_destroy(&(pool->queue_not_full));
    }
    free(pool);
    pool = NULL;

    return 0;
}

int threadpool_all_threadnum(threadpool_t *pool) {
    int all_threadnum = -1;                 // 总线程数

    pthread_mutex_lock(&(pool->lock));
    all_threadnum = pool->live_thr_num;     // 存活线程数
    pthread_mutex_unlock(&(pool->lock));

    return all_threadnum;
}

int threadpool_busy_threadnum(threadpool_t *pool) {
    int busy_threadnum = -1;                // 忙线程数

    pthread_mutex_lock(&(pool->thread_counter));
    busy_threadnum = pool->busy_thr_num;
    pthread_mutex_unlock(&(pool->thread_counter));

    return busy_threadnum;
}

//int is_thread_alive(pthread_t tid)
//{
//    int kill_rc = pthread_kill(tid, 0);     //发0号信号,测试线程是否存活
//    if (kill_rc == ESRCH) {
//        return false;
//    }
//    return true;
//}

/* 线程池中的线程,模拟处理业务 */
void *process(void *arg) {
    printf("thread 0x%x working on task %d\n ", (unsigned int) pthread_self(), (int) arg);
    sleep(1);                           //模拟 小---大写
    printf("task %d is end\n", (int) arg);

    return NULL;
}

/* 向线程池中 添加一个任务 */
//threadpool_add(thp, process, (void*)&num[i]);   /* 向线程池中添加任务 process: 小写---->大写*/

int threadpool_add(threadpool_t *pool, void *(*function)(void *arg), void *arg) {
    pthread_mutex_lock(&(pool->lock));

    /* ==为真,队列已经满, 调wait阻塞 */
    while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) {
        pthread_cond_wait(&(pool->queue_not_full), &(pool->lock));
    }

    if (pool->shutdown) {
        pthread_cond_broadcast(&(pool->queue_not_empty));
        pthread_mutex_unlock(&(pool->lock));
        return 0;
    }

    /* 清空 工作线程 调用的回调函数 的参数arg */
    if (pool->task_queue[pool->queue_rear].arg != NULL) {
        pool->task_queue[pool->queue_rear].arg = NULL;
    }

    /*添加任务到任务队列里*/
    pool->task_queue[pool->queue_rear].function = function; // 设置回调函数为process
    pool->task_queue[pool->queue_rear].arg = arg; // 回调函数对应的参数
    pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;       /* 队尾指针移动, 模拟环形 */
    pool->queue_size++; // 队列中的实际任务数+1

    /*添加完任务后,队列不为空,唤醒线程池中 等待处理任务的线程*/
    pthread_cond_signal(&(pool->queue_not_empty));
    pthread_mutex_unlock(&(pool->lock));

    return 0;
}

int main() {
    threadpool_t *thp = threadpoll_create(3, 100, 100);
    printf("poll inited");

    int num[20], i;
    for (i = 0; i < 20; ++i) {
        num[i] = i;
        printf("add task %d\n", i);

        /*int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg) */

        threadpool_add(thp, process, (void *) &num[i]);   /* 向线程池中添加任务 */
    }

    sleep(10);
    threadpool_destroy(thp);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值