Morecoin unity jquery facebook stack casting Fries 河南普通话 sketch up教程 传智播客python pmp视频 android实战项目 ps视频教程全集完整版 less官网 android常用布局 android调试工具 windows杀进程命令 python3基础教程 python读取mysql数据 eclipse安装python java注释 java介绍 java的socket通信 linux安装 linux用户 图吧导航怎么样 pyh 数科阅读器 战地联盟辅助 视频相册制作软件 teraterm 3d看图软件 幽灵行动多少钱 苹果手机耳机没声音 文字转音频软件 dbgview dll下载站 python画散点图 shellif 恶意软件清理
当前位置: 首页 > 学习教程  > 编程语言

并发:信号量

2020/11/4 14:09:41 文章标签:

信号量(Semaphore)是用于进程/线程间传递信号的一个整数值。在信号量上只可以进行三种操作,即初始化、递减和递增,这三种操作都是原子操作。 递减semWait():信号量的值减1,如果小于0,则当前线程被阻塞,否则…

信号量(Semaphore)是用于进程/线程间传递信号的一个整数值。在信号量上只可以进行三种操作,即初始化、递减和递增,这三种操作都是原子操作。

递减semWait():信号量的值减1,如果小于0,则当前线程被阻塞,否则可以继续执行,递减操作也称为P操作;

递增semSignal():信号量的值加1,如果小于等于0,则从等待队列中唤醒一个线程,使其就绪,递增操作也称为V操作。

信号量模型也被称为PV原语。java语言中,信号量模型由java.util.concurrent.Semaphore实现。semWait()对应的是acquire(),semSignal()对应的是release()。

1、二元信号量

二元信号量指的是信号量的值只能是1或者0,这实际上就是一个互斥锁,同一时刻只能有一个线程执行临界代码。

比如:

//信号量被初始化为1
static final Semaphore s = new Semaphore(1);

static void foo(){
  //信号量减1后等于0,保证其他线程无线进入
  s.acquire();
  try{
    //临界区
  }finally{
    //finally保证信号量的释放
    s.release();
  }
}

2、信号量与互斥锁有何不同?

信号量可以允许多个线程访问同一个临界区

当信号量是二元的情况下,信号量就是互斥锁。当信号量更大时,就可以使得更多的线程同时进入临界区。

同时,信号量也无法唤醒多个阻塞的线程去争抢锁,只能唤醒一个阻塞的线程。

信号量的一个java的例子:限流器。

当我们需要重复利用对象池中N个对象,如果一个线程占用了某个对象,则占用期间不允许其他线程使用。可以使用信号量来实现多个线程同时去对象池中取对象。

public class ObjPool<T,R>{
  final List<T> pool;
  //信号量
  final Semaphore sem;
  
  //构造器
  ObjPool(int size, T t){
    //使用线程安全的容器Vector,避免多个线程同时取容器中同一位置的对象
    pool = new Vector<T>(){};
    for(int i = 0; i < size; ++i){
      pool.add(t);
    }
    sem = new Semaphore(size);
  }
  
  //线程执行函数
  R exec(Function<T,R> func){
    T t = null;
    //信号量减1
    sem.acquire();
    try{
      //取容器中0号位置的对象
      t = pool.remove(0);
      //使用回调函数执行
      return func.apply(t);
    }finally{
      //将对象放回线程池
    	pool.add(t); 
      //信号量加1,唤醒1个阻塞的线程
      sem.release();
    }
  }
  
}

//创建对象池(单例的),里面放置10个Long类型的2
  ObjPool<Long, String> pool = new ObjPool<Long, String>(10,2);
  //某一线程从线程池中取对象,并在回调函数中应用
  pool.exec(t->{
    System.out.println(t);
    return t.toString();
  });

参考资料:
《操作系统精髓与设计原理》
《java并发编程实战》


本文链接: http://www.dtmao.cc/news_show_350093.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?