`
zy3381
  • 浏览: 155679 次
  • 性别: Icon_minigender_1
  • 来自: 昆明
社区版块
存档分类
最新评论

操作系统同步算法(三)

阅读更多
上一篇文章中,我们通过增加一个变量作为标识,从而判断出读者和写者所共享的缓冲区是否有内容,从而实现读写交替,而不是一个线程不停的运行,另外一个“饿死”。

实际上,操作系统里出了互斥锁,还提供了信号量来实现并发情况下的同步。

/**
**读写互斥问题
**读的时候不能写,写的时候不能读
**读写交替(使用信号量)
**/
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
//声明一把互斥锁
pthread_mutex_t mutex;
sem_t sem;
void writer(void)
{
    while(1)
    {
        sem_post(&sem);//V操作,信号量+1
        pthread_mutex_lock(&mutex);//加锁
        
        printf("writer加锁成功,开始写...\n");
        sleep(5);

        printf("writer写操作结束,释放互斥锁\n");
            
        pthread_mutex_unlock(&mutex);//释放互斥锁
    }
}

void reader(void)
{
    while(1)
    {
        sem_wait(&sem);//P操作,信号量-1
        pthread_mutex_lock(&mutex);//加锁
        
        printf("reader加锁成功,开始读...\n");
        sleep(5);

        printf("reader读操作结束,释放互斥锁\n");

        pthread_mutex_unlock(&mutex);//释放互斥锁
    }  
}

int main(void)
{
    printf("初始化互斥锁\n");
    pthread_mutex_init(&mutex,NULL);
    printf("初始化信号量\n");
    sem_init(&sem,0,0);
    pthread_t thread_writer;
    pthread_t thread_reader;
    printf("开始读写线程\n");
    pthread_create(&thread_reader,NULL,(void *)reader,NULL);
    pthread_create(&thread_writer,NULL,(void *)writer,NULL);
    printf("回收线程\n");
    pthread_join(thread_reader,NULL);
    pthread_join(thread_writer,NULL);
    printf("运行结束\n");
    return 0;
}


这里我们通过引入信号量(sem_t )类型的变量来解决共享缓冲区判断问题,这里要注意的一个地方是PV操作的位置以及互斥锁的加锁和信号量的PV操作顺序问题。

首先讨论一下PV操作的位置。P在我们的程序中就是sem_post()函数,作用是对信号量进行加1,这里很显然我们应该将P操作放在写者的线程中。同理,读者中的sem_wait()函数代表的就是V操作,作用是对信号量进行减1,很显然应该放在读者线程中。

关于PV操作和加锁的先后顺序。我最开始是先加锁,再进行P或者V,但是运行的时候我发现程序完全阻塞了,没有任何输出,分析了一下原因:如果是读者先加锁,加锁成功,然后进行V操作,这个时候因为信号量初始值为0,所以进入阻塞。我们再来看写者会是什么情况,写者试图加锁,因为读者已经加锁了,所以阻塞。至此,两个线程全部阻塞。。。所以要注意,一定是先P或者V操作,再进行加锁,否则会造成全部阻塞的死锁现象。









分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics