一、能避免同步吗?

取得锁会由于下面原因导致成本非常高:

    取得由竞争的锁须要在虚拟机的层面上执行很多其它的程序代码。

    要取得有竞争锁的线程总是必须等到锁被释放后。

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 线程第三版 第五章 极简同步技巧 读书笔记的更多相关文章

  1. Java 线程第三版 第四章 Thread Notification 读书笔记

    一.等待与通知 public final void wait() throws InterruptedException      等待条件的发生. public final void wait(lo ...

  2. Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记

    第一章 Thread导论 为何要用Thread ? 非堵塞I/O      I/O多路技术      轮询(polling)      信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...

  3. Java 线程第三版 第九章 Thread调度 读书笔记

    一.Thread调度的概述 import java.util.*; import java.text.*; public class Task implements Runnable { long n ...

  4. Java 线程第三版 第八章 Thread与Collection Class 读书笔记

        JDK1.2引入最有争议性的改变是将集合类默觉得不是Thread安全性的. 一.Collection Class的概述 1. 具有Threadsafe 的Collection Class: j ...

  5. 光源 材质 简析——基于《real time rendering》第三版 第五章

    对于真是世界的渲染,有三个重要的组成部分,光源,材质,以及摄像机.下面,我们一个一个来简单介绍一下. 光源:方向光,点光源,聚光灯.但是,在和物体表面交互的时候,光源对物体表面的影响是依赖光的辐照度( ...

  6. 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记

    造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...

  7. Javascript模式(第五章对象创建模式)------读书笔记

    一 命名空间模式 1 命名空间模式的代码格式 var MYAPP={ name:"", version:"1.0", init:function(){ } }; ...

  8. 《CLR.via.C#第三版》第二部分第13章节 接口 读书笔记(七)

    这章的书写感觉很普通,是些基础的认知知识. 其中一点的重要认知,泛型接口的好处(其实也是使用泛型的好处之一):编译时类型安全&处理值类型时减少装箱. 再说点书上没有的.本来这些知识我打算另外分 ...

  9. 《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)

    终于讲到泛型了.当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解.很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻. 泛型的概念:泛型是 ...

随机推荐

  1. nodeJS学习(10) --- 事件模块

    转载:http://www.cnblogs.com/zhongweiv/p/nodejs_events.html 目录 简介及资料 事件常用函数及使用 emitter.on(event, listen ...

  2. L#中 int.TryParse 有问题

    今天发现了一个 L# 的异常..因此记录一下 List<string> strList = new List<string>(); ; i<; ++i) { ; j< ...

  3. yoga安装kali备忘(连接wifi)

    kali 2.0 iso win8 下安装 用 WinSetupFromUSB-1-6-beta2 写入u盘,正常安装系统 启动连接wifi 搜索信号,获取ssid iw wlan0 scan 查看是 ...

  4. 属性动画详解一(Property Animation)

    效果图: Android动画有3类: 1.View Animation (Tween Animation) 2.Drawable Animation (Frame Animation) 2.Prope ...

  5. postgresql 10 数据类型 (完整版)

    官方数据类型document https://www.postgresql.org/docs/10/static/datatype.html PostgreSQL拥有丰富的数据类型供用户使用.用户也可 ...

  6. springBoot 打成jar包

    1.一种方式通过cmd 窗口进行打包 配置maven 环境变量 进入到项目中  运行 mvn clean 然后运行mvn package 进行打包 2.通过idea 进行打包 (1)pom 中安装打包 ...

  7. Codeforces 731B Coupons and Discounts(贪心)

    题目链接 Coupons and Discounts 逐步贪心即可. 若当前位为奇数则当前位的下一位减一,否则不动. #include <bits/stdc++.h> using name ...

  8. 全栈一路坑(4)——创建博客的API

    上一篇博客:全站之路一路坑(3)——使用百度站长工具提交站点地图 这一篇要搭建一个API平台,一是为了给博客补充一些功能,二是为以后做APP提供数据接口. 首先需要安装Django REST Fram ...

  9. 解决每次启动Office都出出现设置向导的问题

    昨天不知道怎么地,每次打开Excel都会出现"正在配置Office"的设置向导,并且修复.重置用户均无法解决. 在网上搜索了一下,找到了一个解决方法:把"C:\Progr ...

  10. Flexible and Economical UTF-8 Decoder

    http://bjoern.hoehrmann.de/utf-8/decoder/dfa/