线程同步与互斥

一.线程互斥

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;

}

结果:

 

结果说明:锁粒度越小越好

二、线程安全和可重入:

beforeafter间键入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);

}

结果:

 

猜你喜欢

转载自blog.csdn.net/xuruhua/article/details/79948485