一.线程互斥
1.
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
int g_count = 0;
void *ThreadEntry(void *)
{
(void *)arg;
size_t i = 0;
for (; i < 50000; ++i)
{
++g_count;
}
return NULL;
}
int main()
{
pthread_t tid[2];
size_t i = 0;
for (; i < 2; ++i){
pthread_create(&tid[i], NULL, ThreadEntry, NULL);
}
for (i=0; i < 2; ++i){
pthread_join(tid[i], NULL);
}
printf("g_count=%d\n", g_count);
return 0;
}
结果不同,因为两个线程的调度顺序没有说明
结果:
2. 使用互斥锁mutex后
(1)
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
# include<unistd.h>
# include<sched.h>
int g_count=0;
pthread_mutext_t g_mutex;
void *ThreadEntry(void *arg)
{
(void *)arg;
size_t i = 0;
pthread_mutex_lock(&g_mutex);
for (; i < 50000; ++i)
{
++g_count;
}
pthread_mutex_unlock(&g_mutex);
return NULL;
}
int main()
{
pthread_mutex_init(&g_mutex,NULL);
pthread_t tid[2];
size_t i = 0;
for (; i < 2; ++i){
pthread_create(&tid[i], NULL, ThreadEntry, NULL);
}
for (i=0; i < 2; ++i){
pthread_join(tid[i], NULL);
}
printf("g_count=%d\n", g_count);
pthread_mutex_destory(&g_mutex);
return 0;
}
结果:
(2)
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
int g_count = 0;
void *ThreadEntry(void *)
{
(void *)arg;
size_t i = 0;
for (; i < 50000; ++i)
{
pthread_mutex_lock(&g_count);
++g_count;
pthread_mutex_unlock(&g_count);
}
return NULL;
}
int main()
{
pthread_t tid[2];
size_t i = 0;
for (; i < 2; ++i){
pthread_create(&tid[i], NULL, ThreadEnter, NULL);
}
for (i=0; i < 2; ++i){
pthread_join(tid[i], NULL);
}
printf("g_count=%d\n", g_count);
return 0;
}
结果:
结果说明:锁粒度越小越好
二、线程安全和可重入:
在before和after间键入ctrl+c,产生了死锁(因为加了两次锁,信号处理函数没有执行完,便ctrl+c了)
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
int g_count = 0;
pthread_mutex_t g_mutex;
void Func(){
pthread_mutex_lock(&g_count);
printf("before ++g_count\n");A
++g_count;
sleep(2);
printf("after ++g_count\n");
pthread_mutex_unlock(&g_count);
}
void Handler(int sig)
{
(void)sig;
Func();
}
void *ThreadEnter(void *arg)
{
(void)arg;
size_t i = 0;
for (; i < 50000; ++i)
{
Func();
}
return NULL;
}
int main()
{
signal(SIGINT, Handler);
pthread_mutex_init(&g_count, NULL);
pthread_t tid[2];
size_t i = 0;
for (; i < 1; ++i){
pthread_create(&tid[i], NULL, ThreadEnter, NULL);
}
for (i=0; i < 1; ++i){
pthread_join(tid[i], NULL);
}
printf("g_count=%d\n", g_count);
pthread_mutex_destroy(&g_mutex);
return 0;
}
结果:
三、线程同步
1、未加入同步机制
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
# include<unistd.h>
# include<string.h>
void *r1(void *arg)
{
(void)arg;
while (1){
printf("pass ball\n");
usleep(678123);
}
}
void *r2(void *arg)
{
(void)arg;
while (1){
printf("receive ball\n");
usleep(123456);
}
}
int main()
{
pthread_t t1, t2;
pthread_create(&t1, NULL, r1, NULL);
pthread_create(&t2, NULL, r2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
结果:
2、加入了同步机制
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
# include<unistd.h>
# include<string.h>
pthread_cond_t cond;
pthread_mutex_t mutex;
void *r1(void *arg)
{
(void)arg;
while (1){
printf("pass ball\n");
pthread_cond_signal(&cond);
usleep(678123);
}
}
void *r2(void *arg)
{
(void)arg;
while (1){
pthread_cond_wait(&cond, &mutex);
printf("receive ball\n");
usleep(123456);
}
}
int main()
{
pthread_t t1, t2;
pthread_cond_t_init(&cond, NULL);
pthread_mutex_t_init(&mutex,NULL);
pthread_create(&t1, NULL, r1, NULL);
pthread_create(&t2, NULL, r2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
结果:
四、生产者与消费者模型:
1. 用条件变量的方式实现:
(1)未带同步互斥锁
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
# include<unistd.h>
# include<string.h>
//用链式栈实现一个交易场所
typedef struct msg{
struct msg *next;
int data;
}Node;
//往往使用链表的头节点指针来代替整个链表
//实现一个带头节点,不带环的单向链表
//实现三种关系
struct msg *head = NULL;
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_t threads[CONSUMERS_COUNT + PRODUCERS_COUNT];
//实现一个带头节点,不带环的单向链表
Node *CreateNode(int value)
{
Node *new_node = (Node *)malloc(sizeof(Node));
new_node->data = value;
new_node->next = NULL;
return new_node;
}
void DestroyNode(Node *node)
{
free(node);
}
void Push(Node *head, int value)
{
Node *new_node = CreateNode(value);
new_node->next = head->next;
head->next = new_node;
}
//value作为一个输出型参数,保存着我们删除的节点信息
void Pop(Node *head, int *value)
{
if (head->next == NULL){
//空链表
return;
}
Node *to_delete = head->next;
head->next = to_delete->next;
*value = to_delete->data;
DestroyNode(to_delete);
}
void *Prodduct(void *arg)
{
(void)arg;
int id = 0;
while (1){
Push(head, id);
printf("Product:%d\n", id);
id++;
usleep(456123);
}
return NULL;
}
void *Consumer(void *arg)
{
(void)arg;
while (1){
int value = -1;
Pop(head, &value);
printf("Consumer:%d\n", value);
usleep(123456);
}
return NULL;
}
结果:
(2)带同步互斥锁
代码:
# include<stdio.h>
# include<stdlib.h>
# include<pthread.h>
# include<unistd.h>
# include<string.h>
//用链式栈实现一个交易场所
typedef struct msg{
struct msg *next;
int data;
}Node;
//往往使用链表的头节点指针来代替整个链表
//实现一个带头节点,不带环的单向链表
//实现三种关系
struct msg *head = NULL;
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_t threads[CONSUMERS_COUNT + PRODUCERS_COUNT];
//实现一个带头节点,不带环的单向链表
Node *CreateNode(int value)
{
Node *new_node = (Node *)malloc(sizeof(Node));
new_node->data = value;
new_node->next = NULL;
return new_node;
}
void DestroyNode(Node *node)
{
free(node);
}
void Push(Node *head, int value)
{
Node *new_node = CreateNode(value);
new_node->next = head->next;
head->next = new_node;
}
//value作为一个输出型参数,保存着我们删除的节点信息
void Pop(Node *head, int *value)
{
if (head->next == NULL){
//空链表
return;
}
Node *to_delete = head->next;
head->next = to_delete->next;
*value = to_delete->data;
DestroyNode(to_delete);
}
void *Prodduct(void *arg)
{
(void)arg;
int id = 0;
while (1){
pthread_mutex_lock(&mutex);
Push(head, id);
printf("Product:%d\n", id);
id++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
usleep(456123);
}
return NULL;
}
void *Consumer(void *arg)
{
(void)arg;
while (1){
int value = -1;
pthread_mutex_lock(&mutex);
if (head->next == NULL)
{
pthread_cond_wait(&cond, &mutex);
}
Pop(head, &value);
printf("Consumer:%d\n", value);
pthread_mutex_unlock(&mutex);
usleep(123456);
}
return NULL;
}
int main()
{
pthread_t Productor, Consumer;
pthread_cond_init(&cond, NULL);
pthread_create(&Prodeuctor, NULL, Product, NULL);
pthread_create(&Consumer, NULL,Consume, NULL);
pthread_join(Productor, NULL);
pthread_join(Consumer, NULL);
pthread_cond_destroy(&cond);
}
结果:
2. 用POSIX信号量实现
代码:
# include<stdio.h>
# include<pthread.h>
# include<unistd.h>
//用一个基于数组实现的队列实现一个交易场所
#define MAX_SIZE 1000
typedef struct Queue{
int data[MAX_SIZE];
int head;
int tail;
int size;
}Queue;
Queue queue;
void Init(Queue *q)[
q->head = q->tail = q->size = 0;
void Push(Queue *q, int value)
{
if (q->size >= MAX_SIZE){
return;
}
q->data[q->tail++] = value;
if (q->tail >= MAX_SIZE)
{
q->tail = 0;
}
++q->size;
return;
}
void Pop(Queue *q, int *value)
{
if (q->size == 0)
{
return;
}
*value = q->data[q->head];
++q->head;
if (q->head >= MAX_SIZE)
{
q->head = 0;
}
--q->size;
return;
}
//实现三种关系
sem_t g_lock;
sem_t g_data;//队列元素的个数
sem_t g_blank;//空白的个数
//实现两种角色
void *Product(void *arg)
{
(void)arg;
int count = 0;
while (1)
{
//申请空白资源
//sem_wait(&g_blank);
//sem_wait(&g_lock);
//lock
Push(&queue, count);
printf("Product %d\n", count);
//unlock
//sem_post(&g_lock);
//数据资源多了一个
//sem_post(&g_data);
++count;
usleep(456123);
}
}
void Consume(void *arg)
{
(void)arg;
while (1){
int value = -1;
//先申请一个数据资源
//sem_wait(&g_data);
//sem_wait(&g_lock);
Pop(&queue, &value);
printf("Consumer %d\n", value);
//sem_post(&g_lock);
//sem_post(&g_blank);
//消费完毕,释放了一个空白资源
usleep(123456);
}
}
int main()
{
sem_init(&g_lock, 0, 1);
sem_init(&g_data, 0, 0);
sem_init(&g_blank, 0, MAX_SIZE);
Init(&queue);
pthread_t productor, consumer;
pthread_create(&prodeuctor, NULL, Product, NULL);
pthread_create(&consumer, NULL,Consume, NULL);
pthread_join(productor, NULL);
pthread_join(consumer, NULL);
sem_destroy(&g_lock);
sem_destroy(&g_data);
sem_destroy(&g_blank);
}
结果: