Linux | 什么是互斥锁以及如何用代码实现互斥锁

互斥锁(为了实现多个线程对同一共享资源的争用管理)

在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,多人共用一台打印机,为了使大家都能有序公正的使用这台打印机,肯定要进行某种管理。
在线程里有这么一把锁——互斥锁(mutex),互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁( lock )和解锁( unlock )

【互斥锁的特点】:

1. 原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量;

2. 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量;

3. 非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。

【互斥锁的操作流程如下】:

1. 在访问共享资源后临界区域前,对互斥锁进行加锁

2. 在访问完成后释放互斥锁导上的锁。 

3. 对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。

下面是常用的关于互斥锁的一些函数

#include <pthread.h>
#include <time.h>

int pthread_mutex_init(pthread_mutex_t *mutex, 
						const pthread_mutexattr_t *attr);
/* 该函数的功能是初始化一个互斥锁*//*这种初始化互斥锁的方式叫做动态方式*/

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
/*使用静态的方法初始化互斥锁,类似于我们定义一个指针时,将这个指针指向nullptr,
即 char* p =nullptr*/

int pthread_mutex_lock(pthread_mutex_t *mutex);
/* 这个函数的功能是对互斥锁上锁,若此时互斥锁已经上锁,说明此时共享资源正在被使用,则调用者该函数者一直阻塞,直到互斥锁解锁后再上锁。*/

int pthread_mutex_trylock(pthread_mutex_t *mutex);
/* 调用该函数时,若互斥锁未加锁,则上锁,返回 0;若互斥锁已加锁,则函数直接返回失败,即 EBUSY。*/

int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
const struct timespec *restrict abs_timeout);
/* 当线程试图获取一个已加锁的互斥量时,pthread_mutex_timedlock 互斥量原语允许绑定线程阻塞时间。*/

int pthread_mutex_unlock(pthread_mutex_t *mutex);
/*对指定的互斥锁解锁。*/

int pthread_mutex_destroy(pthread_mutex_t *mutex);
/* 销毁指定的一个互斥锁。互斥锁在使用完毕后,必须要对互斥锁进行销毁,以释放资源。*/

示例代码【阻塞模式】

//使用互斥量解决多线程抢占资源的问题
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
 
char* buf[5]; //字符指针数组  全局变量  相当于共享资源
int pos; //用于指定上面数组的下标
 
//1.定义互斥量
pthread_mutex_t mutex;//相当于互斥锁
 
void *task(void *p)
{
    //3.使用互斥量进行加锁
    pthread_mutex_lock(&mutex);
 
    buf[pos] = (char *)p;
    sleep(1);
    pos++;
 
    //4.使用互斥量进行解锁
    pthread_mutex_unlock(&mutex);
}
 
int main(void)
{
    //2.初始化互斥量, 默认属性
    pthread_mutex_init(&mutex, NULL);
 
    //1.启动一个线程 向数组中存储内容
    pthread_t tid, tid2;
    pthread_create(&tid, NULL, task, (void *)"zhangfei");
    pthread_create(&tid2, NULL, task, (void *)"guanyu");
    //2.主线程进程等待,并且打印最终的结果
    pthread_join(tid, NULL);
    pthread_join(tid2, NULL);
 
    //5.销毁互斥量
    pthread_mutex_destroy(&mutex);
 
    int i = 0;
    printf("字符指针数组中的内容是:");
    for(i = 0; i < pos; ++i)
    {
        printf("%s ", buf[i]);
    }
    printf("\n");
    return 0;
}

多次运行结果】

【示例代码2 】

#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <string.h>
 
int main (void)
{
    int err;
    struct timespec tout;//存放时间信息的结构体
    struct tm *tmp;
    char buf[64];

    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //静态的定义一个互斥锁
    pthread_mutex_lock (&lock);//上锁

    printf ("mutex is locked\n");

    clock_gettime (CLOCK_REALTIME, &tout);//获取当前时间信息,并存放在tout中
    tmp = localtime (&tout.tv_sec); //将保存的时间信息赋值给tmp

    strftime (buf, sizeof (buf), "%r", tmp);
    printf ("current time is %s\n", buf);//显示当前时间

    tout.tv_sec += 10;//将之前已保存的时间加上10秒

    err = pthread_mutex_timedlock (&lock, &tout);/*尝试获取互斥锁,若此时互斥锁已上锁,则设定阻塞的时间为10秒*/

    clock_gettime (CLOCK_REALTIME, &tout);//获取当前时间信息,并存放在tout中
    tmp = localtime (&tout.tv_sec);//将保存的时间信息赋值给tmp

    strftime (buf, sizeof (buf), "%r", tmp);
    printf ("the time is now %s\n", buf);//显示当前时间

    if (err == 0)
        printf ("mutex locked again\n");
    else 
        printf ("can`t lock mutex again:%s\n", strerror (err));

    pthread_mutex_destroy(&lock);
    return 0;
}

【运行结果】

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
上面已经给出了Linux互斥锁实验的代码示例,这里再详细一些地解释一下。 ```c #include <pthread.h> #include <stdio.h> #include <stdlib.h> pthread_mutex_t mutex; int resource = 0; void *resource_owner_thread(void *arg) { pthread_mutex_lock(&mutex); resource++; printf("Resource Owner: Incremented resource to %d\n", resource); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } void *resource_user_thread(void *arg) { pthread_mutex_lock(&mutex); printf("Resource User: Using resource with value %d\n", resource); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } int main(int argc, char **argv) { pthread_t threads[10]; pthread_mutex_init(&mutex, NULL); // Create resource owner thread pthread_create(&threads[0], NULL, resource_owner_thread, NULL); // Create multiple resource user threads int i; for (i = 1; i < 10; i++) { pthread_create(&threads[i], NULL, resource_user_thread, NULL); } // Wait for all threads to complete for (i = 0; i < 10; i++) { pthread_join(threads[i], NULL); } pthread_mutex_destroy(&mutex); return 0; } ``` 首先,需要包含`pthread.h`头文件,该头文件中包含了使用互斥锁的相关函数和数据类型。然后,创建一个全局变量`resource`,用于模拟共享资源。 接下来,定义两个线程函数`resource_owner_thread`和`resource_user_thread`。其中,`resource_owner_thread`线程用于模拟资源的占用,它使用`pthread_mutex_lock`函数互斥锁进行锁操作,然后对共享资源进行修改,最后使用`pthread_mutex_unlock`函数互斥锁进行解锁操作。`resource_user_thread`线程用于模拟资源的访问,它也使用`pthread_mutex_lock`函数互斥锁进行锁操作,然后读取共享资源的值,最后使用`pthread_mutex_unlock`函数互斥锁进行解锁操作。 在主函数中,首先定义了一个`pthread_mutex_t`类型的互斥锁变量`mutex`,并使用`pthread_mutex_init`函数进行初始化。然后,创建一个资源占用线程和多个资源访问线程。在创建线程时,使用`pthread_create`函数指定线程函数和参数,并将线程标识符保存在`threads`数组中。最后,使用`pthread_join`函数等待所有线程执行完毕,然后使用`pthread_mutex_destroy`函数销毁互斥锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值