是操作系统能够进行运算的调度的最小单位。
它被包括在进程中,是进程中的实际运作单位。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并发执行不同的任务。
x
//创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
//获取线程id
pthread_t pthread_self(void);
Compile and link with -pthread.
//发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。
//pthread_cancel调用并不等待线程终止,它只提出请求。线程在取消请求(pthread_cancel)发出后会继续运行,
//直到到达某个取消点(CancellationPoint)。取消点是线程检查是否被取消并按照请求进行动作的一个位置.
int pthread_cancel(pthread_t thread);
//线程的终止可以是调用了pthread_exit或者该线程的例程结束。也就是说,一个线程可以隐式的退出,也可以显式的调用pthread_exit函数来退出。
void pthread_exit(void *retval);
//等待线程结束,thread表示线程id,retval表示线程传出线程死亡原因
int pthread_join(pthread_t thread, void **retval);
//retval = NULL表示不想知道线程死亡原因
//让线程自行了断,主线程不管
int pthread_detach(pthread_t thread);
xxxxxxxxxx
/*************************************************************************
> File Name: exit.c
> Author:
> Mail:
> Created Time: Mon 31 Jan 2022 01:07:16 PM CST
************************************************************************/
void* thrf1(void* arg) {
printf("thread 1 returning\n");
return (void*)1;
}
void *thrf2(void *arg) {
printf("thread 2 exiting\n");
pthread_exit((void*)2);
return NULL;
}
void *thrf3(void *arg) {
while (1) {
printf("thread 3 sleep 1s\n");
sleep(1);
}
return NULL;
}
int main() {
pthread_t tid; //线程id
void *status; //接收线程死亡原因
pthread_create(&tid, NULL, &thrf1, NULL);
pthread_join(tid, &status);
printf("thread 1 exit code %ld\n", (long)status);
pthread_create(&tid, NULL, &thrf2, NULL);
pthread_join(tid, &status);
printf("thread 2 exit code %ld\n", (long)status);
pthread_create(&tid, NULL, thrf3, NULL);
sleep(3);
pthread_cancel(tid);
pthread_join(tid, &status);
printf("thread 3 exit code %ld\n", (long)status);
return 0;
}
xxxxxxxxxx
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER; //互斥变量初始化
pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
xxxxxxxxxx
/*************************************************************************
> File Name: addnum.c
> Author:
> Mail:
> Created Time: Mon 31 Jan 2022 03:17:20 PM CST
************************************************************************/
int cnt = 0;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
void *cntadd(void *arg) {
int val;
for (int i = 1; i <= 100; i++) {
//pthread_mutex_trylock(&mtx);
pthread_mutex_lock(&mtx);
val = cnt;
printf("%p: %d\n", (void*)pthread_self(), val);
cnt = val + 1;
pthread_mutex_unlock(&mtx);
}
return NULL;
}
int main() {
pthread_t td1, td2, td3;
pthread_create(&td1, NULL, &cntadd, NULL);
pthread_create(&td2, NULL, &cntadd, NULL);
pthread_create(&td3, NULL, &cntadd, NULL);
//不想得到线程死亡信息,等待线程结束
pthread_join(td1, NULL);
pthread_join(td2, NULL);
pthread_join(td3, NULL);
return 0;
}
线程A需要等待某个条件成立才能继续往下执行,现在这个条件不成立,线程A阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A执行。
xxxxxxxxxx
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
struct timespec {
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds [0 .. 999999999] */
};
int pthread_cond_destroy(pthread_cond_t *cond);
xxxxxxxxxx
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
、
限时等待一个条件变量
xxxxxxxxxx
time_t cur = time(NULL); 获取当前时间。
struct timespec t; 定义timespec 结构体变量t
t.tv_sec = cur+1; 限时1秒
pthread_cond_timedwait (&cond, &mutex, &t);
xxxxxxxxxx
/*************************************************************************
> File Name: cond.c
> Author:
> Mail:
> Created Time: Mon 31 Jan 2022 07:52:31 PM CST
************************************************************************/
typedef struct Goods{
int data;
struct Goods *next;
} Goods;
Goods *head = NULL;
pthread_mutex_t headMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t hasGoods = PTHREAD_COND_INITIALIZER;
void *producer(void *arg) {
Goods *newGoods;
while (1) {
newGoods = (Goods*)malloc(sizeof(Goods));
newGoods->data = rand() % 101;
//加锁
pthread_mutex_lock(&headMutex);
//头插法
newGoods->next = head;
head = newGoods;
//解锁
//pthread_mutex_unlock(&headMutex);
//触发环境变量
//pthread_cond_signal(&hasGoods);
pthread_cond_broadcast(&hasGoods);
//解锁
pthread_mutex_unlock(&headMutex);
//为啥先触发环境变量再解锁,因为先解锁的话,如果刚刚解锁就有一个不是阻塞环境变量线程的获取锁。
printf("producer goods data: %d\n\n", newGoods->data);
sleep(rand() % 2);
}
return NULL;
}
void *consumer(void *arg) {
Goods *oldHead = NULL;
while (1) {
//加锁
pthread_mutex_lock(&headMutex);
while (!head) { //没有商品
//等待事件触发,释放锁
pthread_cond_wait(&hasGoods, &headMutex);
}
//有商品
oldHead = head;
head = head->next;
//解锁
pthread_mutex_unlock(&headMutex);
printf("thread id:%ld, consumer goods data: %d\n\n", pthread_self(), oldHead->data);
//释放商品内存
free(oldHead);
sleep(rand() % 3);
}
return NULL;
}
int main() {
srand(time(NULL));
pthread_t td1, td2, td3, td4, td5;
pthread_create(&td1, NULL, &producer, NULL);
pthread_create(&td2, NULL, &consumer, NULL);
pthread_create(&td3, NULL, &consumer, NULL);
pthread_create(&td5, NULL, &consumer, NULL);
pthread_create(&td4, NULL, &consumer, NULL);
pthread_join(td1, NULL);
pthread_join(td2, NULL);
pthread_join(td3, NULL);
pthread_join(td4, NULL);
pthread_join(td5, NULL);
return 0;
}
xxxxxxxxxx
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_post(sem_t *sem);
int sem_destroy(sem_t *sem);
int sem_getvalue(sem_t *sem);
第一个参数:
pshared:
value:表示可用资源数量
xxxxxxxxxx
/*************************************************************************
> File Name: sem.c
> Author:
> Mail:
> Created Time: Mon 31 Jan 2022 10:24:14 PM CST
************************************************************************/
//创建5个信号的量
int q[Q_NUM]; //循环队列
int head, tail;
sem_t blankNumber, goodsNumber;
void *producer(void *arg) {
while (1) {
sem_wait(&blankNumber);
q[tail] = rand() % 100 + 1;
printf("producer goods %d\n", q[tail]);
tail = (tail + 1) % Q_NUM;
sem_post(&goodsNumber);
sleep(rand() % 2);
}
return NULL;
}
void *consumer(void *arg) {
while (1) {
sem_wait(&goodsNumber);
printf("consumer goods %d\n", q[head]);
q[head] = 0;
head = (head + 1) % Q_NUM;
sem_post(&blankNumber);
sleep(rand() % 3);
}
return NULL;
}
int main() {
srand(time(NULL));
sem_init(&blankNumber, 0, Q_NUM); // 空位数量
sem_init(&goodsNumber, 0, 0); // 商品数量
pthread_t pid1, pid2, pid3, cid1, cid2, cid3, cid4, cid5;
pthread_create(&pid1, NULL, &producer, NULL);
pthread_create(&cid1, NULL, &consumer, NULL);
pthread_create(&pid2, NULL, &producer, NULL);
pthread_create(&cid2, NULL, &consumer, NULL);
pthread_create(&pid3, NULL, &producer, NULL);
pthread_create(&cid3, NULL, &consumer, NULL);
pthread_create(&cid4, NULL, &consumer, NULL);
pthread_create(&cid5, NULL, &consumer, NULL);
pthread_join(pid1, NULL);
pthread_join(cid1, NULL);
pthread_join(pid2, NULL);
pthread_join(cid2, NULL);
pthread_join(pid3, NULL);
pthread_join(cid3, NULL);
pthread_join(cid4, NULL);
pthread_join(cid5, NULL);
return 0;
}