简单的线程池的实现及多线程面试题

第一题:线程的基本概念、线程的基本状态及状态之间的关系?

线程,有时称为轻量级进程,是CPU使用的基本单元;它由线程ID、程序计数器、寄存器集合和堆栈组成。它与属于同一进程的其他线程共享其代码段、数据段和其他操作系统资源(如打开文件和信号)。

线程有四种状态:新生状态、可运行状态、被阻塞状态、死亡状态。状态之间的转换如下图所示:

第二题:线程与进程的区别?

1、 线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。
2、 一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个进程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
3、 系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,出了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
4、 与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表中少多了。
5、 进程是系统所有资源分配时候的一个基本单位,拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。

第三题:多线程有几种实现方法,都是什么?

  1. 继承 Thread 类
  2. 实现 Runnable 接口再 new Thread(YourRunnableOjbect)

第四题:多线程同步和互斥有几种实现方法,都是什么?

线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模式下的方法有:事件,信号量,互斥量。

第五题:多线程同步和互斥有何异同,在什么情况下分别使用他们?举例说明。

线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。

1

2、以下多线程对int型变量x的操作,哪几个不需要进行同步(D)
A. x=y; B. x++; C. ++x; D. x=1;

    详见:后面系列解析

3、多线程中栈与堆是公有的还是私有的 (C)

    A:栈公有, 堆私有

    B:栈公有,堆公有

    C:栈私有, 堆公有

    D:栈私有,堆私有

4、临界区(Critical Section)和互斥量(Mutex)

    两者都可以用于同一进程中不同子线程对资源的互斥访问。

    互斥量是内核对象,因此还可以用于不同进程中子线程对资源的互斥访问。

    互斥量可以很好的解决由于线程意外终止资源无法释放的问题。

5、一个全局变量tally,两个线程并发执行(代码段都是ThreadProc),问两个线程都结束后,tally取值范围。

    inttally = 0;//glable

    voidThreadProc()

    {

          for(inti = 1;i <= 50;i++)

               tally += 1;

    }

    答:[50,100]
/*************************************************************************
 > File Name: threadpool.h
 > Author:  jinshaohui
 > Mail:    [email protected]
 > Time:    18-10-19
 > Desc:    
 ************************************************************************/

#ifndef _THREAD_POOL_LOCK_H_
#define _THREAD_POOL_LOCK_H_

/*任务*/
typedef struct _task_t
{
	void (*func)(void *arg);
    void *arg;
	struct _task_t *next;
}task_t;

typedef struct _task_queue_t
{
	task_t    *tasks;             /*任务队列*/
    int       queue_front;             /*队头*/
    int       queue_rear;              /*队尾*/
	int       queue_size;              /*队列当前的大小*/
    int       queue_max_size;          /*队列容纳的最大任务数*/
}task_queue_t;

typedef struct _lock_pool_t
{
	pthread_mutex_t  lock;             /*锁住整个结构体*/
	pthread_cond_t   queue_is_empty;   /*线程池为空时*/
	pthread_cond_t   queue_not_full;   /*任务队列不为满时*/
    pthread_cond_t   queue_not_empty;  /*任务队列不为空时*/

	pthread_t *threads;                /*存放线程ID*/
    

	/*线程池信息*/
	int thread_max_num;               /*最大线程数*/
	int pool_shutdown;                /*线程池退出*/

    task_queue_t task_queue;
}lock_pool_t;

enum 
{
	POOL_ERROR,
	POOL_WARNING,
	POOL_INFO,
	POOL_DEBUG
};


#define POOL_QUEUE_IS_EMPTY(pool) (0 == pool->task_queue.queue_size)
#define POOL_QUEUE_IS_FULL(pool) (pool->task_queue.queue_max_size == pool->task_queue.queue_size)


lock_pool_t * pool_create(int thread_max_num,int queue_max_size);
void pool_destory(lock_pool_t* pool);
void pool_thread_func(void *args);
int pool_add_task(lock_pool_t *pool,task_t *task);

#endif
/*************************************************************************
 > File Name: threadpool.c
 > Author:  jinshaohui
 > Mail:    [email protected]
 > Time:    18-10-19
 > Desc:    
 ************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<signal.h>
#include<assert.h>
#include"./threadpool.h"

#define debug(level,...)\
	do{\
		if(level <=POOL_DEBUG)\
		{\
			printf("\r\n###threadid[%u],line[%d],%s:",pthread_self(),__LINE__,__FUNCTION__);\
	        printf(__VA_ARGS__);\	
		}\
	}while(0)


lock_pool_t * pool_create(int thread_max_num,int queue_max_size)
{
	int i = 0;
	int res = 0;
	lock_pool_t *pool = NULL;

	/*创建线程池*/
	pool = (lock_pool_t*)malloc(sizeof(lock_pool_t));
	if(pool == NULL)
	{
		debug(POOL_ERROR,"pool malloc failed..\r\n");

		return NULL;
	}

	memset(pool,0,sizeof(lock_pool_t));

	/*线程ID分配空间*/
	pool->threads = ( pthread_t *)malloc(sizeof(pthread_t) * thread_max_num);
	if(pool->threads == NULL)
	{
		pool_free(pool);
        debug(POOL_ERROR,"pool threads malloc failed\r\n");
		return NULL;
	}
	memset(pool->threads,0, sizeof(pthread_t)* thread_max_num);
	/*创建任务队列 并初始化*/
	pool->task_queue.tasks = (task_t *)malloc(sizeof(task_t)*queue_max_size);
	if(pool->task_queue.tasks == NULL)
	{
		pool_free(pool);
        debug(POOL_ERROR,"pool task queue malloc failed\r\n");
		return NULL;
	}
	memset(pool->task_queue.tasks,0, sizeof(task_t)* queue_max_size);
	pool->task_queue.queue_front = 0;
	pool->task_queue.queue_rear = 0;
	pool->task_queue.queue_size = 0;
	pool->task_queue.queue_max_size = queue_max_size;
	
    /*条件变量及互斥锁初始化*/
	if ((pthread_mutex_init(&(pool->lock),NULL) != 0)
		|| (pthread_cond_init(&(pool->queue_is_empty),NULL) != 0)
		|| (pthread_cond_init(&(pool->queue_not_full),NULL) != 0)
		|| (pthread_cond_init(&(pool->queue_not_empty), NULL) != 0))
	{
		pool_free(pool);
        debug(POOL_ERROR,"pool lock mutex add cond init failed\r\n");
		return NULL;
	}

	/*启动多线程*/
    for(i = 0 ; i < thread_max_num; i ++)
	{
         res = pthread_create(&(pool->threads[i]),NULL,pool_thread_func,(void*)pool);
		 if (res != 0)
		 {
             debug(POOL_ERROR,"pool pthread create %d failed\r\n",i);
             pool_destory(pool);
		     return NULL;
		 }
	}

	/*信息初始化*/
	pool->thread_max_num = thread_max_num;
	pool->pool_shutdown = 0;


	return pool;
}

void pool_free(lock_pool_t *pool)
{

	if(pool == NULL)
	{
		return;
	}

	if(pool->threads)
	{
		free(pool->threads);
	}

	if(pool->task_queue.tasks)
	{
		free(pool->task_queue.tasks);
		pthread_mutex_lock(&(pool->lock));
		pthread_mutex_destroy(&(pool->lock));
		pthread_cond_destroy(&(pool->queue_is_empty));
		pthread_cond_destroy(&(pool->queue_not_full));
		pthread_cond_destroy(&(pool->queue_not_empty));
	}

	free(pool);

    return;
}

void pool_destory(lock_pool_t* pool)
{
	int i = 0;
	if (pool == NULL)
	{
		return;
	}
	
	pthread_mutex_lock(&(pool->lock));
	while(!POOL_QUEUE_IS_EMPTY(pool))
	{
		pthread_cond_wait(&(pool->queue_is_empty),&(pool->lock));
	}
	pthread_mutex_unlock(&(pool->lock));

	pool->pool_shutdown = 1;


	pthread_cond_broadcast(&(pool->queue_not_empty));

	for (i = 0; i < pool->thread_max_num; i++)
	{
		pthread_join((pool->threads[i]),NULL);
	}

	pool_free(pool);

	return;
}

void pool_thread_func(void *args)
{
	lock_pool_t *pool = (lock_pool_t *)args;
	task_t ptask = {0};

	while(1)
	{
		pthread_mutex_lock(&(pool->lock));

		while((POOL_QUEUE_IS_EMPTY(pool)) && (!pool->pool_shutdown))
		{
			pthread_cond_broadcast(&(pool->queue_is_empty));
			debug(POOL_DEBUG,"thread %u,is waiting \n",pthread_self());
			pthread_cond_wait(&(pool->queue_not_empty),&(pool->lock));

		}

		/*线程池关闭时*/
		if(pool->pool_shutdown)
		{
			debug(POOL_DEBUG,"thread %u,is exit \n",pthread_self());
			pthread_mutex_unlock(&(pool->lock));
			pthread_exit(NULL);
		}

        ptask.func = pool->task_queue.tasks[pool->task_queue.queue_front].func;
        ptask.arg = pool->task_queue.tasks[pool->task_queue.queue_front++].arg;
		pool->task_queue.queue_front %= pool->task_queue.queue_max_size;
		pool->task_queue.queue_size--;

		/*发送信号 可以添加任务*/
		if ((pool->task_queue.queue_size + 1) == pool->task_queue.queue_max_size)
		{
		    pthread_cond_broadcast(&(pool->queue_not_full));
		}

		pthread_mutex_unlock(&(pool->lock));

		if(ptask.func != NULL)
		{
			ptask.func(ptask.arg);
		}

	}
	pthread_exit(NULL);
	return;
}

int pool_add_task(lock_pool_t *pool,task_t *task)
{
    pthread_mutex_lock(&(pool->lock));

	while((POOL_QUEUE_IS_FULL(pool)) && (pool->pool_shutdown == 0))
	{
		pthread_cond_wait(&(pool->queue_not_full),&(pool->lock));
	}

	if( pool->pool_shutdown)
	{
		pthread_mutex_unlock(&(pool->lock));
		return -1;
	}

	pool->task_queue.tasks[pool->task_queue.queue_rear].func = task->func;
	pool->task_queue.tasks[pool->task_queue.queue_rear++].arg = task->arg;
	pool->task_queue.queue_rear %= pool->task_queue.queue_max_size;
	pool->task_queue.queue_size++;
    
	/*队列为空时,需要唤醒线程*/
	if (pool->task_queue.queue_size == 1)
	{
		pthread_cond_broadcast(&(pool->queue_not_empty));
	}

	pthread_mutex_unlock(&(pool->lock));

	debug(POOL_DEBUG,"\r\n add task %u",(int)task->arg);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/jsh13417/article/details/83422851