自炫锁2-b

2023-12-13 16:23:39

1.

自旋锁
自旋锁也是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。
无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。
但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者进入睡眠状态。但是自旋锁不会引起申请者睡眠,如果自旋锁已经被占用,调用者就一直循环在那里判断占用者是否已经释放了锁,“自旋”一词就是因此而得名(空转锁)。
自旋锁主要用于Linux内核同步。
?

相关函数

1)初始化锁。
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
2)阻塞加锁,若互斥锁已经被其它线程上锁,则调用者一直阻塞等待,直到被解锁后才上锁。

int pthread_spin_lock(pthread_spinlock_t *lock);
3)非阻塞加锁,若互斥锁未加锁,则上锁,若互斥锁已加锁,则函数立即返回失败.

int pthread_spin_trylock(pthread_spinlock_t*lock);
4)解锁。
int pthread_spin_unlock(pthread_spinlock_t*lock);

5)销毁锁,释放资源。
int pthread _spin_destroy(pthread_spinlock_t *lock);

自旋锁也存在优先唤醒的问题。

//b  自选
#include <unistd.h>
#include <pthread.h>
#include <string.h>
char buffer[101];        //全局共享的buffer.
pthread_spinlock_t spin; //声明自旋锁
void *pthfun(void *arg)
{
    for (int ii = 0; ii < 3; ii++)
    {

        printf("%d:%ld:lock...\n",time(0),(long)arg);
        pthread_spin_lock(&spin);
        printf("%d:%ld:lock ok. \n",time(0),(long)arg);

        //操作共享的全局变量。
        sprintf(buffer,"%d:%ld,%d",time(0),pthread_self(),ii);
        sleep(5);

        pthread_spin_unlock(&spin);
        printf("%d:%ld:unlock... \n",time(0),(long)arg);
        usleep(100);
    }
}
int main()
{

    pthread_spin_init(&spin,PTHREAD_PROCESS_PRIVATE); //初始化锁。
    pthread_t pthid1,pthid2;
    pthread_create(&pthid1,NULL,pthfun,(void *)1);
    pthread_create(&pthid2,NULL,pthfun,(void *)2);
    pthread_join(pthid1,NULL);

    pthread_join(pthid2,NULL);
    pthread_spin_destroy(&spin); //销毁锁。
    return 0;
}

这段代码使用自旋锁保护了全局共享的缓冲区 `buffer`,并在两个线程中进行了并发访问。

每个线程的执行流程如下:

1. 线程获取自旋锁,进入临界区。
2. 线程操作全局共享的缓冲区 `buffer`。
3. 线程释放自旋锁,退出临界区。

这个程序使用 `pthread_spin_lock()` 和 `pthread_spin_unlock()` 函数来获取和释放自旋锁。在两个线程中并行执行时,它们会交替获取和释放自旋锁来保护全局共享的缓冲区。注意到 `buffer` 数组是全局共享的,如果不使用自旋锁来进行保护,会产生竞争条件导致多个线程同时访问和修改该缓冲区,导致不可预知的结果。

当线程运行时, `sprintf()` 函数会把当前时间戳、线程 ID 和循环计数器的值格式化到 `buffer` 缓冲区,在紧接着的 5 秒钟内通过 `sleep()` 函数模拟线程执行其他的任务。由于 `buffer` 缓冲区是全局共享的,它的内容可能会被其他线程读取和修改,因此需要使用自旋锁进行保护。

值得注意的是,这个程序在销毁自旋锁之前调用了 `pthread_join()` 函数来等待两个线程的执行完成,这是因为如果在等待线程执行完成之前销毁锁,会导致未定义的行为。

需要指出的是,自旋锁通常是在共享资源访问竞争不激烈的情况下使用,而且实现的正确性也需要根据实际情况进行评估和测试。

结果:

1702177416:2:lock...
1702177416:2:lock ok. 
1702177416:1:lock...
1702177421:1:lock ok. 
1702177421:2:unlock... 
1702177421:2:lock...
1702177426:1:unlock... 
1702177426:2:lock ok. 
1702177426:1:lock...
1702177431:2:unlock... 
1702177431:1:lock ok. 
1702177431:2:lock...
1702177436:1:unlock... 
1702177436:2:lock ok. 
1702177436:1:lock...
1702177441:2:unlock... 
1702177441:1:lock ok. 
1702177446:1:unlock... 

理解 : 就是

两边交替 打印

一个 如果对方 已经拿到锁, 就等待?

等对方 释放 ,? 我们 这边? 就 可以拿到锁 了;

文章来源:https://blog.csdn.net/weixin_48434590/article/details/134905235
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。