美文网首页
并发控制(三)

并发控制(三)

作者: GUISHANL | 来源:发表于2019-05-05 20:28 被阅读0次

生产消费问题描述

有一个或多个生产者产生数据,并放到buffer,
一个消费者一次取一条数据
一次只允许一个生产者或消费者进入buffer
buffer不能并行操作(互斥)
生产者不能向非空buffer写数据,消费者不能取空buffer数据(同步)

生产消费者解决方案

有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费.为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区中;消费者进程可以从一个缓冲区中取走产品去消费。
问题的解?

伪代码实现

items代表缓冲区已经使用的资源数,spaces代表缓冲区可用资源数
mutex代表互斥锁
buf[N] 代表缓冲区,其内容类型为item
in、out代表第一个资源和最后一个资源

var items = 0, space = N, mutex = 1;
var in = 0, out = 0;
item buf[N] = { NULL };

producer {
    while( true ) {
        wait( space );  // 等待缓冲区有空闲位置, 在使用PV操作时,条件变量需要在互斥锁之前
        wait( mutex );  // 保证在product时不会有其他进程访问缓冲区

        // product
        buf.push( item, in );  // 将新资源放到buf[in]位置 
        in = ( in + 1 ) % N;

        signal( mutex );  // 唤醒的顺序可以不同
        signal( items );  // 通知consumer缓冲区有资源可以取走
    }
}

consumer {
    while( true ) {
        wait( items );  // 等待缓冲区有资源可以使用
        wait( mutex );  // 保证在consume时不会有其他进程访问缓冲区

        // consume
        buf.pop( out );  // 将buf[out]位置的的资源取走
        out = ( out + 1 ) % N;

        signal( mutex );  // 唤醒的顺序可以不同
        signal( space );  // 通知缓冲区有空闲位置
    }
}

不能将线程里两个wait的顺序调换否则会出现死锁。例如(调换后),将consumer的两个wait调换,在producer发出signal信号后,如果producer线程此时再次获得运行机会,执行完了wait(space),此时,另一个consumer线程获得运行机会,执行了 wait(mutex) ,如果此时缓冲区为空,那么consumer将会阻塞在wait(items),而producer也会因为无法获得锁的所有权所以阻塞在wait(mutex),这样两个线程都在阻塞,也就造成了死锁。

读写问题

有一个共享的数据对象:
允许多个读者进程同时读;
一次只允许一个写者进程写;当一个写者正在写时,不允许其他任何读者或写者同时访问该共享对象。

读者优先

当至少已有一个读者正在读时,随后的读者直接进入,开始读数据对象,但写者将等待。
但一个写者正在写时,随后到来的读者和写者都等待。

信号量的设置:
一次只能让一个写者或一堆读者访问数据。
设一互斥信号量wsem,初值为1。
正在读数据的读者数目由全局变量readcount表示(初值=0),它被多个读者互斥访问。
(第1个读者需对数据加锁,最后1个读者对数据解锁)
为readcount设一互斥信号量x,初值为1。

void reader(){
    while(true){
        semWait(x);
        readcount++;
        if(readcount == 1)
            semWait(wsem);
        semSignal(x);
        /*读数据对象*/
        semWait(x);
        readcount--;
        if(readcount == 0)
            semSignal(wsem);
        semSignal(x);
    }
}
 
void  writer(){
    while(true){
        semWait(wsem);
        /*写数据对象*/
        semSignal(wsem);
    }
}

读者操作类似于去图书馆看书,有一个阿姨在门口登记一样,登记的时候是互斥的,进去一个就加一,同样出去也是一样的操作。

相关文章

  • 数据库并发控制——悲观锁、乐观锁、MVCC

    三种并发控制:悲观并发控制、乐观并发控制、多版本并发控制。 悲观并发控制(又名“悲观锁”,Pessimistic ...

  • 并发控制(三)

    生产消费问题描述 有一个或多个生产者产生数据,并放到buffer,一个消费者一次取一条数据一次只允许一个生产者或消...

  • MySQL系列之三 -- -并发(MVCC)

    MySQL 并发控制如何实现 MySQL 如何实现高并发? 一 并发控制 抛开MySQL,通过技术上来讨论并发控制...

  • 乐观锁与悲观锁

    乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段 悲观并发控制(悲观锁) 它可以阻止一个...

  • iOS多线程随笔

    1. 多线程的并发控制 1.1 在CGD中快速实现多线程的并发控制 NSOperationQueue来处理并发控制...

  • 你应该了解的MySQL锁分类

    MySQL中的锁 锁是为了解决并发环境下资源竞争的手段,其中乐观并发控制,悲观并发控制和多版本并发控制是数据库并发...

  • Linux 驱动开发之并发控制

    1 设备驱动的并发控制概览 2 参考 Linux并发控制

  • 一文详解分布式数据库并发控制

      并发控制是数据库系统实现的一个难点。本文分为三个部分对目前的分布式并发控制技术进行浅析。一、从用户并发访问可能...

  • MySQL多版本并发控制 - MVCC

    并发控制 实现事务隔离的机制,称之为并发控制 所谓并发控制,就是保证并发执行的事务在某一隔离级别上的正确执行的机制...

  • 并发工具包之CountDownLatch|CyclicBarri

    在java的并发包中为我们提供了三种并发控制的手段,他们分别是CountDownLatch|CyclicBarri...

网友评论

      本文标题:并发控制(三)

      本文链接:https://www.haomeiwen.com/subject/kabfoqtx.html