sychronized、wait、notify、notifyAll、sleep

在多线程环境下,为了防止多个线程同时调用同一个方法、修改同一份变量,造成数据读取结果混乱,可以使用synchronized关键字,对一个方法或者代码块实现同步调用,即只能一个线程调用完此方法后,下一个线程才能调用此方法。

当synchronized修饰的是一个类方法时,使用的是此类的Monitor实现同步(锁)。

当synchronized修饰的是一个实例方法时,使用的是此实例的Monitor实现同步(锁)。

当synchronized修饰的是一个代码块时,使用的是括号中变量的Monitor实现同步(锁)。

在StringBuffer、Hashtable、Vector等类中,为了实现方法同步,大量使用了sychronized关键字修饰方法。

当sychronized修饰的方法或者代码块,执行sleep时,进入time_waiting阶段,并会继续持有锁,直到sleep结束,或者被interrupted,继续执行,直到释放锁。

当sychronized修饰的方法或者代码块,执行wait时,进入waiting阶段,并释放持有的锁,当收到notify通知,或者被interrupted后,会重新竞争获取到锁,才会继续运行。注意,此时虽然处于同步方法中,但其在wait时锁被释放了,只有重新竞争获得锁,才能继续运行。

在sychronized修饰的方法或者代码块中,如果执行notify,会唤醒一个waiting(同一个对象锁)中的线程进入runnable阶段,等到退出sychronized区域,waiting的线程获得锁继续执行进入running阶段;如果执行notifyAll方法,会唤醒所有waiting(同一个对象锁)中的线程,等到当前线程退出sychronized区域,所有waiting的线程竞争锁,未竞争获得锁的线程再次进入waiting阶段,等待唤醒。

ReentrantLock、Condition

使用ReentrantLock类实例化一个lock实例,并可以通过lock实例新建一个Condition实例。

使用时,先用lock实例的lock方法,获得锁,在获得锁的期间可以使用此lock的Condition实例,进行await、signal、singalAll方法,发送信号,进行线程间通信。

举一个阻塞队列的例子:

通过lock对象,新建了两个Condition:notEmpty、notFull。

执行add操作时,会检查list的元素个数是否达到最大值,达到时,等待notFull信号。

执行take操作时,会检查list的元素个数是否为0,为0时,等待notEmpty信号。

add执行成功时,会发送notEmpty信号,通知执行take的线程,等到add操作的lock执行unlock后,去获取数据。

take执行成功时,会发送notFull信号,通知执行add的线程,等到take操作的lock执行unlock后,在去添加数据。

注意:在Conditon发送各种信号之前,创建他们的lock必须执行lock()操作,获取锁;在Conditon发送各种信号之后,创建他们的lock必须执行unlock()操作,释放锁。

class MyQueue {
private ReentrantLock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
private AtomicInteger count = new AtomicInteger(0);
private List<String> list = new LinkedList<String>();
private final int MaxCount = 10; public void add(String str) {
lock.lock();
try {
while (count.get() > MaxCount) {
notFull.await();
}
list.add(str);
count.incrementAndGet();
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public String take() {
String retStr = null;
lock.lock();
try {
while (count.get() == 0) {
notEmpty.await();
}
retStr = list.remove(0);
count.decrementAndGet();
notFull.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return retStr;
}
}

最新文章

  1. 计应152第六组Sprint计划会议
  2. 异步|同步&amp;阻塞|非阻塞
  3. jquery+jplayer实现歌词同步的mp3音乐播放器效果
  4. 设置ArcGIS的外观改回到出厂
  5. android复合控件
  6. Ajax返回xml类型数据
  7. HDOJ 1226 超级密码(bfs)
  8. python获取当前路径的方法
  9. 转)ZooKeeper的实现分析
  10. BZOJ_3170_[Tjoi2013]松鼠聚会_切比雪夫距离+前缀和
  11. Windows apache-flume-1.6.0+Kafka+Es
  12. 源码安装python +NGINX 的坎坷路 +uwsgi安装 部署django 的CRM项目
  13. 图文解说Win7系统机器上发布C#+ASP.NET网站
  14. 我的pwn笔记
  15. nuxt 2
  16. cmd怎么删除Oracle数据库中的用户实例
  17. Netty权威指南之BIO(Block Input/Output,同步阻塞I/O通信)通信模型
  18. spring+ibatis事务管理配置
  19. 牛客练习赛19 C-托米航空公司
  20. 【UVa】Jump(dp)

热门文章

  1. java设计模式 策略
  2. Deferred Shading,延迟渲染(提高渲染效率,减少多余光照计算)【转】
  3. 【bzoj5093】 [Lydsy1711月赛]图的价值 组合数+斯特林数+NTT
  4. J2EE 的体系结构
  5. IO模型之三Reactor 和 Proactor IO设计模式
  6. 黑马学习CSS之CSS模块化规范全部组成 CSS属性列表
  7. COCO2018 stuff分割
  8. SQL语句之行操作
  9. docker 部署 笔记
  10. bzoj4548: 小奇的糖果 题解