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

操作系统同步算法(一)

阅读更多
    最近接触了一些多线程的程序设计,主要涉及到使用多线程对一个缓冲区的数据进行读写。以前觉得多线程好像也不怎么难,到这时候才发现原来是自己所接触到的多线程程序太简单了。好了,废话不多说,直接切入主题,操作系统同步算法。
   
    本科时候所学习的操作系统课程,里面有一个非常重要的部分是关于进程的同步,考试也是必考内容,以前一直感觉晕晕的,想不到这个时候验证了“出来混总是要还的”这句话。以前没理解好,现在来恶补一下。多线程作为现代操作系统的一个基本特征,很多地方和进程的设计理念是类似的,就比如同步算法。

    我们知道,当多个线程同时运行时,是由操作系统对其进行调度,线程的运行顺序是我们无法控制的。这个时候,传统的结构化程序自顶向下的分析思想就显得捉襟见肘了。而事实是,不仅在程序分析上会变得很麻烦,程序对资源的访问的控制也需要进行非常仔细的掂量。关于“读脏”数据等并发引起的问题就不进行详细叙述。

    我们来看第一个非常简单的例子,非常经典的读者/写者问题。

    问题简单描述:有一个读者和一个写者,当写者在进行写作的时候,读者不能阅读,读者阅读的时候,写者不能进行写作。也就是说,读者和写者只能有一个运行,另外一个要阻塞。

算法是用C语言在Linux下实现的

/**
**读写互斥问题
**读的时候不能写,写的时候不能读
**
**/
#include<stdio.h>
#include<pthread.h>
//声明一把互斥锁
pthread_mutex_t mutex;

void writer(void)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        printf("writer加锁成功,开始写...\n");
        sleep(2);
        printf("writer写操作结束,释放互斥锁\n");
        pthread_mutex_unlock(&mutex);
    }
}

void reader(void)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        printf("reader加锁成功,开始读...\n");
        sleep(2);
        printf("reader读操作结束,释放互斥锁\n");
        pthread_mutex_unlock(&mutex);
    }  
}

int main(void)
{
    printf("初始化互斥锁\n");
    pthread_mutex_init(&mutex,NULL);
    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;
}


注意:编译的时候要加上-lpthread
编译命令示例:gcc -o mutex.exe mutex.c -lpthread

    这个程序由于设计上不是很合理,会进入一个无限循环,所以在控制台下运行以后要使用Ctrl+C来强行结束程序的运行,不过不影响整个算法的主要流程。

    我们运行以后可以发现一个很严重的问题,读者或者写者的其中一个可能会长期占据着互斥锁的加锁权,从而导致另外一个线程长期没有机会运行,导致一种线程“饿死”现象。

    在实际的读写过程中,比较正常的一种简单情况是,先写再读,读写交替。下一篇文章我们来改进一下本文的算法,使其达到读写交替的目的。









分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics