一、能避免同步吗?

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

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

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

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. webService的wsdl和restful的wadl的区别

    WebService之WADL和WSDL区别 两者都是基于自然语言描述的Web Application接口 . WADL主要用于Rest基础. Java开发WebService最重要的两个规范: JS ...

  2. 一个javascript继承和使用的例子

    继承可以帮助我们实现代码的重用,把对象的属性写入构造函数,对象的方法写入原型后,以下例子演示继承的使用: 示例的css和js在后 父实例,得到一个间隔1s的轮播: <!DOCTYPE html& ...

  3. BZOJ 1658 Water Slides 滑水

    Water Slides 滑水 [问题描述] It's a hot summer day, and Farmer John is letting Betsy go to the water park ...

  4. .net开发工具集合

    原文发布时间为:2010-10-24 -- 来源于本人的百度文章 [由搬家工具导入] 原文出处:.NET Tools:Ten Must-Have Tools Every Developer Shoul ...

  5. Windows消息钩取

    @author: dlive @date: 2016/12/19 0x01 SetWindowsHookEx() HHOOK SetWindowsHookEx( int idHook, //hook ...

  6. 【剑指offer】构建乘积数组(注意优化空间)

    给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1].不能使用除法 ...

  7. LeetCode OJ-- Length of Last Word

    https://oj.leetcode.com/problems/length-of-last-word/ 对一个字符串遍历,求最后一个单词的长度,如果有 ‘ ’,则切开了. 字符串的最后一个字符为 ...

  8. springBoot 程序入口

    入口类要放在首个package 这样它能扫到所有的包 @SpringBootApplication @EnableScheduling public class App { public static ...

  9. 搭建https本地服务器:如何得到被所有客户端认可的ssl证书

    https,作为http的加密版,作用还是很大的:能够提升网站搜索权重,让你的网站更安全,而且如果你的网站没有使用https的话,将无法作为移动设备原生应用的api接口.可见掌握为网站启用https的 ...

  10. 微信小程序 图片路径自动加上文件目录导致渲染报错问题

    最近 在做小程序时候,发现一些商品图片在渲染时一直报错,也不显示,但是控制台打印出来 的路径却有没有问题 报错提示出错的路径会在前面自动加上“page/**”,思索了之后想到了微信只能解释https的 ...