`
sunwinner
  • 浏览: 202528 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java Concurrency in Practice notes 1

阅读更多

第三遍阅读 Java Concurrency in Practice时,终于意识到要写一些读书笔记。所谓温故而知新,那就从现在开始!

Chapter 2: 线程安全

线程安全性的定义:一个类在被多个线程访问时,可以持续进行正确的行为,这里的正确性指的是该类和它的规约保持一致。良好的规约定义了用于强制对象状态的不变约束以及描述操作影响的后验条件。

无论何时,只要有多于一个的线程访问给定的状态变量,而且其中某个线程会写入该变量,此时必须使用同步来协调线程对该变量的访问。Java中首要的同步机制是Synchronized关键字,它提供了独占锁,除此之外同步还包括volatile变量显式锁原子变量的运用。

在没有正确同步的情况下,如果多个线程访问了同一个变量,你的程序就存在隐患,有3种方法来修复它:

1.不要跨线程共享变量;

2.使状态变量变为不可变,状态变量指的是实例变量或者静态字段,一个无状态对象永远是线程安全的;

3.在访问状态变量时候使用同步。

 

原子性:

在管理对象的状态时,用AtomicLong这样已有的线程安全安全对象管理类的很合适。和非线程安全对象比较,判断一个线程安全对象的可能状态和状态转换要容易得多,这简化了维护和验证线程安全性的工作。

 

Synchronized代码块:

本次不介绍Synchronized机制的另一个重要方面:可见性。

Synchronized是Java提供的强制原子性的内置锁机制,一个Synchronized块有两个部分:锁对象的引用和这个锁保护的代码块。对于Synchronized方法,是跨越了整个方法体的Synchronized块的简述,与Synchronized代码块不同的是,Synchronized方法的锁就是该方法所在的对象自身,而静态Synchronized方法则从Class对象上获取锁。

每个Java对象都可以隐式的扮演用于同步的锁的角色,这些内置的锁被称为内部锁(intrinsic loaks)或者监视器锁(monitor locks)。执行线程进入Synchronized块之前会自动获得锁,而无论通过正常控制流退出还是从块中抛出异常退出,线程都在放弃对Synchronized块的控制之前自动释放锁。获得内部锁的唯一途径是:进入这个内部锁保护的同步块或者方法。

内部锁在Java中扮演了互斥锁的角色,意味着至多只有一个线程可以拥有锁。但内部锁是可重入的(Reentrancy),线程请求获得自己已经占有的锁时会成功,重入意味着所有请求是基于没线程的,而不是每调用的。它的实现是通过为每个锁关联一个请求计数(Acquisition count)和一个占有它的线程。当计数为0时,认为锁是未被占有的。JVM记录锁的占有者,如果同一线程再次请求这个锁,计数将增加;每次占用线程退出同步块,计数器将递减,直到计数器到达0时锁被释放。重入方便了锁行为的封装,简化了面向对象并发代码的开发。例如,如果子类Override了父类的synchronized方法,并调用父类中的方法,如果没有可重入的锁则会发生死锁。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics