第一题:线程的基本概念、线程的基本状态及状态之间的关系?
线程,有时称为轻量级进程,是CPU使用的基本单元;它由线程ID、程序计数器、寄存器集合和堆栈组成。它与属于同一进程的其他线程共享其代码段、数据段和其他操作系统资源(如打开文件和信号)。
线程有四种状态:新生状态、可运行状态、被阻塞状态、死亡状态。状态之间的转换如下图所示:
第二题:线程与进程的区别?
1、 线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。
2、 一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个进程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
3、 系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,出了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
4、 与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表中少多了。
5、 进程是系统所有资源分配时候的一个基本单位,拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。
第三题:多线程有几种实现方法,都是什么?
- 继承 Thread 类
- 实现 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;
}