Linux 线程编程2.0——线程同步-互斥锁

落花浮王杯 提交于 2020-01-17 13:52:54

        当我们需要控制对共享资源的存取的时候,可以用一种简单的加锁的方法来控制。我们可以创建一个读/写程序,它们共用一个共享缓冲区,使用互斥锁来控制对缓冲区的存取。 

  函数 pthread_mutex_init()用来生成一个互斥锁。其函数原型如下:

 

#include<pthread.h>

 

int pthread_mutex_init(pthread_mutex_t *restrict mutexconst pthread_mutexattr_t *restrict attr)

 

第一个参数是互斥变量的地址,第二个参数设置互斥变量的属性,大多数情况下.选择默认属性,则传入空指针 NULL

 

  Pthread_mutex_lock()函数声明开始用互斥锁上锁,此后的代码直至调用 pthread_mutex_ unlock()为止,均被上锁,即同一时间只能被一个线程调用执行。当一个线程执行 pthread_mutex_lock()处时,如果该锁此时被另一个线程使用,那么此线程被阻塞,线程一直阻塞知道另一个线程释放此互斥锁。这两个函数原型是:

 

 int pthread_mutex_lock(pthread_mutex_t *mutex)

 

 int pthread_mutex_unlock(pthread_mutex_t *mutex)

 

  两个函数的参数都是互斥变量的地址。函数执行成功返回 0,否则返回错误号。

 

  互斥锁使用很方便,但是有一个缺点是使用互斥锁的过程中很有可能会出现死锁:两个线程试图同时占有两个资源,并按不同的次序锁定相应的互斥锁,例如两个线程都需要锁定互斥锁 l 和互斥锁 2A 线程锁定了互斥锁 lB 线程了锁定互斥锁 2,此时如果 A 线程在解除互斥锁 l 之前又去锁定互斥锁 2,而 B 恰好又需要去锁定互斥锁 l,这时就出现了死锁。看起来像是绕口令,通俗一点的来解释:线程 A 和线程 B 都需要独占使用 2 个资源,但是他们都分别先占据了一个资源,然后有相互等待另外一个资源的释放,这样的形成了一个死锁。此时我们可以使用函数 pthread_mutex_trylock(),它是函数 pthread_mutex_lock()的非阻塞函数,当它发现死锁不可避免时,它会通过 errno 返回 EBUSY,我们可以针对死锁做出相应的处理。Pthread_mutex_try_lock()的函数原型是:

 

int  pthread_mutex _trylock( pthread_mutex_t*mutex)

 

  当互斥锁不再使用的时候,应当释放互斥变量,函数 pthread _mutex.destory()用来释放一个互斥变量。

代码:

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

char buffer[128];
int buffer_has_data=0;
pthread_mutex_t mutex;

void write_buffer (char *data)
{
    /* 锁定互斥锁*/
    pthread_mutex_lock (&mutex);
    if (buffer_has_data == 0)
    {
        sprintf( buffer, "%s", data);
        buffer_has_data=1;
    }
    /* 打开互斥锁*/
    pthread_mutex_unlock(&mutex);
}

void  read_buffer(void)
{
    while(1){
        /* 锁定互斥锁*/
        pthread_mutex_lock(&mutex);
        if(buffer_has_data == 1)
        {
            printf("Read buffer, data = [%s]\n", buffer);
            buffer_has_data=0;
        }
        /* 打开互斥锁*/
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main ( int argc, char **argv )
{
    char input[128];
    pthread_t reader;
    /* 用默认属性初始化一个互斥锁对象*/
    pthread_mutex_init( &mutex, NULL );
    pthread_create(&reader, NULL, (void *)(read_buffer), NULL);
    while( 1 )
    {
        scanf( "%s", input );
        write_buffer( input );
    }
    return 0;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!