Java 并发(一)

一,并发理论的简介

?1.解释java线程模型

?? java线程模型建立在两个基本的概念之上:

  • ?共享的,默认可见的可变状态:所有线程都可以很容易地共享同一进程中的对象,能够引用的线程都可以修改这些对象
  • 抢占式线程调度:线程调度程序几乎任何时候都能在内核上调入或调出线程(否则无限循环的方法会一种占用CPU)

线程的调度可能会导致方法“半途而费”,并出现状态不一致的对象。某一线程对数据进行修时,会让其他线程无法见到本来应该可见的修改。为了缓解这些风险,Java提出了最后一点要求:

  • 为了保护脆弱的数据,对象可以被锁住

?2.设计理念

? Doug Lea在创造他的里程碑式的作品java.util.concurrent时列出了下面这些最重要的设计原则:

  • 安全性:不管同时发生多少操作都能确保对象保证自相一致
  • 活跃度:在一个活跃的系统中个,所有做出的尝试的活动最终要么取得进展,要么失败。
  • 性能
  • 可重用性

3.系统开销之源

  • 锁的检测
  • 环境切换的次数
  • 线程的个数
  • 调度
  • 内存的局部性:在程序运行中的短时间内,程序访问数据位置的结合限于局部范围内(理解不是很清楚,理解了再来修改博客)
  • 算法的设计

二,块结构并发(JAVA 5之前)

??? 1.同步与锁

????? sychronized的知识就不多说了,不懂的可以网上查查。

?? Java中的同步和锁相关的一些基本事实:

  • 只能锁定对象,不能锁定原始类型(原始类型不是对象)
  • 被锁定的对象数组中的单个对象不会被锁定
  • 同步方法可以视为包含整个方法的同步(this){.....}
  • 静态同步方法会锁定它的class对象
  • 内部类的同步是独立于外部类的
  • sychronized并不是方法签名的组成部分,所以不能出现在接口方法声明中
  • 非同步方法不会查看或关心任何锁的状态,而且同步方法运行时它们任然能够运行
  • Java的线程锁是可重入的。也就是说持有锁的线程在遇到同一个锁的同步点(比如一个同步方法调用同一个类的另外一个同步方法)时是可以继续的

2.线程的状态模型



?

?

3.解决同步问题的一个办法——完全同步对象

完全同步对象必须满足的所有条件

  • 所有field在任何构造方法的初始化都能达到一致的状态
  • 没有公共filed
  • 从任何非私有方法返回后,都可以保证对象实例处于一致的状态
  • 所有方法都可在有限时间内终止
  • 所有方法都是同步的
  • 当处于非一致状态时,不会调用其它实例的方法,不会调用非私有方法

一个完全同步类的例子:



?

?

?

?

完全同步类的缺点很明显:锁会把你的速度拖慢,这也是并发处理方式主要的问题

?

3.Java中确立临界区的关键字为什么是sychronized?而不是"critical"或者是“locked”

? 以前,程序员可能不容易碰到支持多处理器系统,因此并发编程过去主要考虑如何分享CPU时间(多个线程在单核上轮流上位,相互调换)。如今,多核处理器很普遍,我们应该吧多个线程在同一物理时刻运行在不同处理器上(并且很可能会操作共享的数据)。



?

?

被同步的是在不同线程中表示被锁定对象的内存块,也就是说,在sychronized代码块(或者方法)执行完之后,被锁定对象所做的任何修改全部都会在线程释放锁之前刷回到主内存中。当进入一个同步代码块,得到线程锁之后,被锁定对象的任何修改都是从主内存中读出来的,所以在锁定区域代码开始执行之前,持有锁的的线程和锁定对象主内存中的视图同步了


4.关键字volatile

一个volatile域需要遵循如下规则:

  • 线程所见的值在使用之前总会从内存中再读出来
  • 线程所写的值总会在指令完成之前被刷回到主内存中

程序员可以借此编写简化的代码,但是付出的代价是每次访问都要额外刷一次内存。volatile变量不会引起线程锁,所以使用volatile编程不可能发生死锁。更微妙的是volatile编程式真正线程安全的,但是只有写入时不依赖当前状态的变量才应该声明为volatile变量。对于要关注当前状态的变量,只能借助锁保证其绝对安全性。也可以理解volatile只是为了它的通信效果,而不是为了互斥访问。

?

以上内容全部来自《Java程序员修炼之道》如果想具体了解,可以看看原书

?

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。