多线程-------线程的同步与互斥

一、什么是互斥量(mutex)
先来看一段代码:操作共享变量会有问题的售票系统

Makefile
这里写图片描述
mypthread.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int ticket = 100;

void *sell_ticket(void *arg)
{
    char *id  = (char*)arg;
    while(1)
    {
        if(ticket > 0)
        {
            usleep(1000);
            printf("%s get ticket,id is %d\n",(char*)arg,ticket);
            ticket--;
        }
        else
        {
            break;
        }
    }
}

int main()
{
    pthread_t t1,t2,t3,t4;
    pthread_create(&t1,NULL,sell_ticket, "thread 1 is runing");
    pthread_create(&t2,NULL,sell_ticket, "thread 2 is runing");
    pthread_create(&t3,NULL,sell_ticket, "thread 3 is runing");
    pthread_create(&t4,NULL,sell_ticket, "thread 4 is runing");

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);
    return 0;
}

运行之:
这里写图片描述
线程不断买票,买到后面时出现-1,-2

-1 -2意味着什么 意味着票务系统出错了,(数据不一致问题:临界资源有可能在同一时间被多个线程访问,无法保证原子性)

  • 怎样解决:加锁:实现互斥(1、保证一个线程在访问临界资源的时候,其他线程不能访问;2、如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区)

图示一下互斥量(加的锁:在临界区前后 加锁解锁)
这里写图片描述
1、互斥量的相关接口
(1)初始化互斥量

* 方法一:静态分配
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
* 方法二:动态分配
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

//参数
  mutex:要初始化的互斥量
  attr:NULL

全局变量为什么能被线程看到:线程之间资源共享
(2)销毁互斥量

#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);

// 返回值
成功返回0;失败返回错误码

(3)互斥量加锁和解锁(加锁和解锁是原子的)

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex); 
int pthread_mutex_unlock(pthread_mutex_t *mutex);

// 返回值:成功返回0;失败返回错误码

调用pthread_mutex_lock时遇到的情况:

(1)互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功
(2)发起函数调用时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,辣么pthread_mutex_lock调用会陷入阻塞,等待互斥量解锁

改进一下刚开始的票务系统的代码:

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int ticket = 100;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void *sell_ticket(void *arg)
{
    char *id  = (char*)arg;
    while(1)
    {
       // 给临界区加锁
        pthread_mutex_lock(&lock);
        if(ticket > 0)
        {
            usleep(1000);
            printf("%s get ticket,id is %d\n",(char*)arg,ticket);
            ticket--;
             pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
    }
}

int main()
{
     pthread_t t1,t2,t3,t4;
     pthread_create(&t1,NULL,sell_ticket, "thread 1 is runing");
     pthread_create(&t2,NULL,sell_ticket, "thread 2 is runing");
     pthread_create(&t3,NULL,sell_ticket, "thread 3 is runing");
     pthread_create(&t4,NULL,sell_ticket, "thread 4 is runing");

     pthread_join(t1, NULL);
     pthread_join(t2, NULL);
     pthread_join(t3, NULL);
     pthread_join(t4, NULL);

     // 销毁
     pthread_mutex_destroy(&lock);
     return 0;
 }

运行之:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/apt1203jn/article/details/80320276