Java 线程第三版 第五章 极简同步技巧 读书笔记
一、能避免同步吗?
取得锁会由于下面原因导致成本非常高:
取得由竞争的锁须要在虚拟机的层面上执行很多其它的程序代码。
要取得有竞争锁的线程总是必须等到锁被释放后。
1. 寄存器的效应
计算机有一定数量的主寄存器用来存储与程序有关的数据。
从逻辑上的观点来看,每一个Thread都有自己的一组寄存器。当操作系统将某个Thread分配给CPU时,它会把该Thread特有的信息载入到CPU的寄存器中。
在分配不同的Thread给CPU之前,它会将寄存器的信息存下来。
所以Thread间绝不会共享保存在寄存器的数据。
当虚拟机进入synchronized方法或者块时。它必须又一次载入本来已经缓存到自有寄存器上的数据。在虚拟机离开synchroized方法或者块之前,它必须把自有寄存器存入主寄存器中。
2. 重排语句的效应
在单独线程中。程序总是依照代码一行行的运行的。可是假设是多个线程并发,Java并不保证每一个线程run方法的运行顺序,也就是可能当中一个线程运行到一半就会被临时停止。运行其它线程,之后再切换回来。
多个线程间调度运行的无序性就是重排语句的效应。
3. 双重检查的Locking
二、Atomic变量
1. Atomic Class的概述
AtomicInteger, AtomicLong, AtomicBoolean, AtomicRefrences。Atomic的功能实现时通过使用use-level的Java程序无法訪问的固有方法来完毕的。
atomic package支持更复杂的变量类型吗?
一些不支持。比如字符或者浮点。
AtomicStampedReference可以让mark或stamp跟在不论什么对象的引用上。
AtomicMarkableReference提供一个包括对象引用结合boolean的数据结构。
2. 使用Atomic Class
import javax.swing.*;
import java.awt.event.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import javathreads.examples.ch05.*; public class ScoreLabel extends JLabel implements CharacterListener {
private AtomicInteger score = new AtomicInteger(0);
private AtomicInteger char2type = new AtomicInteger(-1);
private AtomicReference<CharacterSource> generator = null;
private AtomicReference<CharacterSource> typist = null; public ScoreLabel (CharacterSource generator, CharacterSource typist) {
this.generator = new AtomicReference(generator);
this.typist = new AtomicReference(typist); if (generator != null)
generator.addCharacterListener(this);
if (typist != null)
typist.addCharacterListener(this);
} public ScoreLabel () {
this(null, null);
} public void resetGenerator(CharacterSource newGenerator) {
CharacterSource oldGenerator; if (newGenerator != null)
newGenerator.addCharacterListener(this); oldGenerator = generator.getAndSet(newGenerator);
if (oldGenerator != null)
oldGenerator.removeCharacterListener(this);
} public void resetTypist(CharacterSource newTypist) {
CharacterSource oldTypist; if (newTypist != null)
newTypist.addCharacterListener(this); oldTypist = typist.getAndSet(newTypist);
if (oldTypist != null)
oldTypist.removeCharacterListener(this);
} public void resetScore() {
score.set(0);
char2type.set(-1);
setScore();
} private void setScore() {
// This method will be explained later in chapter 7
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setText(Integer.toString(score.get()));
}
});
} public void newCharacter(CharacterEvent ce) {
int oldChar2type; // Previous character not typed correctly - 1 point penalty
if (ce.source == generator.get()) {
oldChar2type = char2type.getAndSet(ce.character); if (oldChar2type != -1) {
score.decrementAndGet();
setScore();
}
}
// If character is extraneous - 1 point penalty
// If character does not match - 1 point penalty
else if (ce.source == typist.get()) {
while (true) {
oldChar2type = char2type.get(); if (oldChar2type != ce.character) {
score.decrementAndGet();
break;
} else if (char2type.compareAndSet(oldChar2type, -1)) {
score.incrementAndGet();
break;
}
} setScore();
}
}
}
变量替换
score与char2type变量已经改成atomic变量。
以上resetScroe方法中对两个变量进行改动。尽管使用atomic能保证每一个变量的原子性,可是假设多个线程同一时候运行resetScore方法依旧会出现竞态条件。
有可能一个线程运行resetScore的第一行代码score.set(0);还未运行第二行,而另外一个线程可能已经运行newCharacter方法获取char2type的值,可是之前的线程运行resetScore方法还未对char2type进行改动。由于resetScore整个方法并非原子的。
变更算法
resetGenerator与resetTypist两个方法,以resetGenerator方法为例,将generator变量变成AtomicRerence相同引发上面描写叙述的问题。
通知与Atomic变量
import java.awt.*;
import javax.swing.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import javathreads.examples.ch05.*;public class AnimatedCharacterDisplayCanvas extends CharacterDisplayCanvas implements CharacterListener, Runnable {
private AtomicBoolean done = new AtomicBoolean(true);
private AtomicInteger curX = new AtomicInteger(0);
private AtomicInteger tempChar = new AtomicInteger(0);
private Thread timer = null;public AnimatedCharacterDisplayCanvas() {
startAnimationThread();
}public AnimatedCharacterDisplayCanvas(CharacterSource cs) {
super(cs);
startAnimationThread();
}private void startAnimationThread() {
if (timer == null) {
timer = new Thread(this);
timer.start();
}
}public void newCharacter(CharacterEvent ce) {
curX.set(0);
tempChar.set(ce.character);
repaint();
}protected void paintComponent(Graphics gc) {
char[] localTmpChar = new char[1];
localTmpChar[0] = (char) tempChar.get();
int localCurX = curX.get();Dimension d = getSize();
int charWidth = fm.charWidth(localTmpChar[0]);
gc.clearRect(0, 0, d.width, d.height);
if (localTmpChar[0] == 0)
Java 线程第三版 第五章 极简同步技巧 读书笔记的更多相关文章
- Java 线程第三版 第四章 Thread Notification 读书笔记
一.等待与通知 public final void wait() throws InterruptedException 等待条件的发生. public final void wait(lo ...
- Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记
第一章 Thread导论 为何要用Thread ? 非堵塞I/O I/O多路技术 轮询(polling) 信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...
- Java 线程第三版 第九章 Thread调度 读书笔记
一.Thread调度的概述 import java.util.*; import java.text.*; public class Task implements Runnable { long n ...
- Java 线程第三版 第八章 Thread与Collection Class 读书笔记
JDK1.2引入最有争议性的改变是将集合类默觉得不是Thread安全性的. 一.Collection Class的概述 1. 具有Threadsafe 的Collection Class: j ...
- 光源 材质 简析——基于《real time rendering》第三版 第五章
对于真是世界的渲染,有三个重要的组成部分,光源,材质,以及摄像机.下面,我们一个一个来简单介绍一下. 光源:方向光,点光源,聚光灯.但是,在和物体表面交互的时候,光源对物体表面的影响是依赖光的辐照度( ...
- 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记
造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...
- Javascript模式(第五章对象创建模式)------读书笔记
一 命名空间模式 1 命名空间模式的代码格式 var MYAPP={ name:"", version:"1.0", init:function(){ } }; ...
- 《CLR.via.C#第三版》第二部分第13章节 接口 读书笔记(七)
这章的书写感觉很普通,是些基础的认知知识. 其中一点的重要认知,泛型接口的好处(其实也是使用泛型的好处之一):编译时类型安全&处理值类型时减少装箱. 再说点书上没有的.本来这些知识我打算另外分 ...
- 《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)
终于讲到泛型了.当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解.很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻. 泛型的概念:泛型是 ...
随机推荐
- nodeJS学习(10) --- 事件模块
转载:http://www.cnblogs.com/zhongweiv/p/nodejs_events.html 目录 简介及资料 事件常用函数及使用 emitter.on(event, listen ...
- L#中 int.TryParse 有问题
今天发现了一个 L# 的异常..因此记录一下 List<string> strList = new List<string>(); ; i<; ++i) { ; j< ...
- yoga安装kali备忘(连接wifi)
kali 2.0 iso win8 下安装 用 WinSetupFromUSB-1-6-beta2 写入u盘,正常安装系统 启动连接wifi 搜索信号,获取ssid iw wlan0 scan 查看是 ...
- 属性动画详解一(Property Animation)
效果图: Android动画有3类: 1.View Animation (Tween Animation) 2.Drawable Animation (Frame Animation) 2.Prope ...
- postgresql 10 数据类型 (完整版)
官方数据类型document https://www.postgresql.org/docs/10/static/datatype.html PostgreSQL拥有丰富的数据类型供用户使用.用户也可 ...
- springBoot 打成jar包
1.一种方式通过cmd 窗口进行打包 配置maven 环境变量 进入到项目中 运行 mvn clean 然后运行mvn package 进行打包 2.通过idea 进行打包 (1)pom 中安装打包 ...
- Codeforces 731B Coupons and Discounts(贪心)
题目链接 Coupons and Discounts 逐步贪心即可. 若当前位为奇数则当前位的下一位减一,否则不动. #include <bits/stdc++.h> using name ...
- 全栈一路坑(4)——创建博客的API
上一篇博客:全站之路一路坑(3)——使用百度站长工具提交站点地图 这一篇要搭建一个API平台,一是为了给博客补充一些功能,二是为以后做APP提供数据接口. 首先需要安装Django REST Fram ...
- 解决每次启动Office都出出现设置向导的问题
昨天不知道怎么地,每次打开Excel都会出现"正在配置Office"的设置向导,并且修复.重置用户均无法解决. 在网上搜索了一下,找到了一个解决方法:把"C:\Progr ...
- Flexible and Economical UTF-8 Decoder
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/