多线程间共享数据问题

一、Synchronizedkeyword

atomic一词与“原子”无关,它以前被觉得是物质的最小的单元,不能再被拆解成更小的部分。
当一个方法被声明成synchronized,要执行此方法的thread必须先取得一个token,我们将它称为锁。

一旦该方法取得(或者说是获得)锁,它将执行此方法然后释放掉(或者返回)此锁。无论方法时如何返回的(包含通过异常)该锁会被释放。

二、Volatilekeyword

假设变量被标示为volatile。每次使用该变量时都必须从主寄存器中读出。同样地。每次要写入该变量时,值都必须存入主寄存器。更进一步。Java指定对volatile变量的载入与存储都是atomic的。不管是否是long与double变量。
volatile声明的变量进行++、--操作不能保证原子性。
volatile声明的数组,会让数组的引用变成volatile数组中的元素不是volatile。

三、很多其它竞态条件的讨论

public class ScoreLabel extends JLabel implements CharacterListener {private volatile int score = 0;private int char2type = -1;private CharacterSource generator = null, typist = null;public ScoreLabel (CharacterSource generator, CharacterSource typist) {this.generator = generator;this.typist = typist;if (generator != null)generator.addCharacterListener(this);if (typist != null)typist.addCharacterListener(this);       }public ScoreLabel () {this(null, null);}public synchronized void resetGenerator(CharacterSource newGenerator) {if (generator != null)generator.removeCharacterListener(this);generator = newGenerator;if (generator != null)generator.addCharacterListener(this);        }public synchronized void resetTypist(CharacterSource newTypist) {if (typist != null)typist.removeCharacterListener(this);typist = newTypist;if (typist != null)typist.addCharacterListener(this);}public synchronized void resetScore() {score = 0;char2type = -1;setScore();}private void setScore() {// This method will be explained later in chapter 7SwingUtilities.invokeLater(new Runnable() {public void run() {setText(Integer.toString(score));}});}public synchronized void newCharacter(CharacterEvent ce) {// Previous character not typed correctly - 1 point penaltyif (ce.source == generator) {if (char2type != -1) {score--;setScore();}char2type = ce.character;}// If character is extraneous - 1 point penalty// If character does not match - 1 point penaltyelse {if (char2type != ce.character) {score--;} else {score++;char2type = -1;}setScore();}}
}

此类共享的数据是由实际的得分数、须要被输入的字母与少数持有的字母来源作为登记用的变量等所组成。解决竞态条件问题意味着让这些数据在正确的scope中被同步化。
假设newCharacter方法不能确保同步。当中包括的变量char2type、score变量的改动并不能保证在全部的线程中都能实时的获取到正确的最后一次改动的值,导致基于char2type的推断出现故障,接连导致score也出现故障。
解决的方法是在此类中全部涉及到这两个变量的都把当前类作为同步锁(即每一个方法都加入一个synchronizedkeyword)。目的是在全部线程中调用这些方法都必需要是相互排斥操作,不可能同一时候多个线程调用操作这两个变量的方法,从而保证正确性。

四、显示锁

public class ScoreLabel extends JLabel implements CharacterListener {private volatile int score = 0;private int char2type = -1;private CharacterSource generator = null, typist = null;private Lock scoreLock = new ReentrantLock();public ScoreLabel (CharacterSource generator, CharacterSource typist) {this.generator = generator;this.typist = typist;if (generator != null)generator.addCharacterListener(this);if (typist != null)typist.addCharacterListener(this);       }public ScoreLabel () {this(null, null);}public void resetGenerator(CharacterSource newGenerator) {try {scoreLock.lock();if (generator != null)generator.removeCharacterListener(this);generator = newGenerator;if (generator != null)generator.addCharacterListener(this);} finally {scoreLock.unlock();}}public void resetTypist(CharacterSource newTypist) {try {scoreLock.lock();if (typist != null)typist.removeCharacterListener(this);typist = newTypist;if (typist != null)typist.addCharacterListener(this);} finally {scoreLock.unlock();}}public void resetScore() {try {scoreLock.lock();score = 0;char2type = -1;setScore();} finally {scoreLock.unlock();}}private void setScore() {// This method will be explained later in chapter 7SwingUtilities.invokeLater(new Runnable() {public void run() {setText(Integer.toString(score));}});}public void newCharacter(CharacterEvent ce) {try {scoreLock.lock();// Previous character not typed correctly - 1 point penaltyif (ce.source == generator) {if (char2type != -1) {score--;setScore();}char2type = ce.character;}// If character is extraneous - 1 point penalty// If character does not match - 1 point penaltyelse {if (char2type != ce.character) {score--;} else {score++;char2type = -1;}setScore();}} finally {scoreLock.unlock();}}
}

与上一个样例原理同样,都是涉及char2type、score两个变量改动的方法上都加入锁,当前样例仅是使用第二种语法使用提供的Lock与unLock来加锁解锁操作,在此样例上这两种做法是等价的。之后会讨论synchronized与Lock的不同之处。

五、Lock Scope

public class ScoreLabel extends JLabel implements CharacterListener {private volatile int score = 0;private int char2type = -1;private CharacterSource generator = null, typist = null;private Lock scoreLock = new ReentrantLock();public ScoreLabel (CharacterSource generator, CharacterSource typist) {this.generator = generator;this.typist = typist;if (generator != null)generator.addCharacterListener(this);if (typist != null)typist.addCharacterListener(this);       }public ScoreLabel () {this(null, null);}public void resetGenerator(CharacterSource newGenerator) {try {scoreLock.lock();if (generator != null)generator.removeCharacterListener(this);generator = newGenerator;if (generator != null)generator.addCharacterListener(this);} finally {scoreLock.unlock();}}public void resetTypist(CharacterSource newTypist) {try {scoreLock.lock();if (typist != null)typist.removeCharacterListener(this);typist = newTypist;if (typist != null)typist.addCharacterListener(this);} finally {scoreLock.unlock();}}public void resetScore() {try {scoreLock.lock();score = 0;char2type = -1;setScore();} finally {scoreLock.unlock();}}private void setScore() {// This method will be explained later in chapter 7SwingUtilities.invokeLater(new Runnable() {public void run() {setText(Integer.toString(score));}});}public void newCharacter(CharacterEvent ce) {if (ce.source == generator) {try {scoreLock.lock();// Previous character not typed correctly - 1 point penaltyif (char2type != -1) {score--;setScore();}char2type = ce.character;} finally {scoreLock.unlock();}}// If character is extraneous - 1 point penalty// If character does not match - 1 point penaltyelse {try {scoreLock.lock();if (char2type != ce.character) {score--;} else {score++;char2type = -1;}setScore();} finally {scoreLock.unlock();}}}
}

Lock与unLock能够放到自己须要的不论什么地方。

六、Synchronized块

public class ScoreLabel extends JLabel implements CharacterListener {private volatile int score = 0;private int char2type = -1;private CharacterSource generator = null, typist = null;public ScoreLabel (CharacterSource generator, CharacterSource typist) {this.generator = generator;this.typist = typist;if (generator != null)generator.addCharacterListener(this);if (typist != null)typist.addCharacterListener(this);       }public ScoreLabel () {this(null, null);}public synchronized void resetGenerator(CharacterSource newGenerator) {if (generator != null)generator.removeCharacterListener(this);generator = newGenerator;if (generator != null)generator.addCharacterListener(this);        }public synchronized void resetTypist(CharacterSource newTypist) {if (typist != null)typist.removeCharacterListener(this);typist = newTypist;if (typist != null)typist.addCharacterListener(this);}public synchronized void resetScore() {score = 0;char2type = -1;setScore();}private void setScore() {// This method will be explained later in chapter 7SwingUtilities.invokeLater(new Runnable() {public void run() {setText(Integer.toString(score));}});}public void newCharacter(CharacterEvent ce) {// Previous character not typed correctly - 1 point penaltyif (ce.source == generator) {synchronized(this) {if (char2type != -1) {score--;setScore();}char2type = ce.character;}}// If character is extraneous - 1 point penalty// If character does not match - 1 point penaltyelse {synchronized(this) {if (char2type != ce.character) {score--;} else {score++;char2type = -1;}setScore();}}}
}

在此样例中,被锁住的对象与用在方法的同步化上的是同一个对象:this对象。     

七、选择Locking机制

synchronized与Lock在静态方法(static method)上有所差别,由于在方法上使用synchronized是针对当前对象锁定。而静态方法是全局的,使用这样的办法会使确保正确性添加难度,相反使用Lock由于它与当前对象无关。仅仅须要在方法内设置lock与unlock所以更easy确保多线程同步的正确性。

八、Lock Interface

boolean tryLock()
     仅在调用时锁为空暇状态才获取该锁。 
     假设锁可用,则获取锁,并马上返回值 true。

假设锁不可用。则此方法将马上返回值 false。

此方法的典型使用语句例如以下:

Lock lock = ...;
      if (lock.tryLock()) {
          try {
              // manipulate protected state
          } finally {
              lock.unlock();
          }
      } else {
          // perform alternative actions
      }
     此使用方法可确保假设获取了锁。则会释放锁,假设未获取锁,则不会试图将其释放。

返回:
     假设获取了锁,则返回 true;否则返回 false。

九、Nested Lock

public class ScoreLabel extends JLabel implements CharacterListener {private volatile int score = 0;private int char2type = -1;private CharacterSource generator = null, typist = null;public ScoreLabel (CharacterSource generator, CharacterSource typist) {this.generator = generator;this.typist = typist;if (generator != null)generator.addCharacterListener(this);if (typist != null)typist.addCharacterListener(this);       }public ScoreLabel () {this(null, null);}public synchronized void resetGenerator(CharacterSource newGenerator) {if (generator != null)generator.removeCharacterListener(this);generator = newGenerator;if (generator != null)generator.addCharacterListener(this);        }public synchronized void resetTypist(CharacterSource newTypist) {if (typist != null)typist.removeCharacterListener(this);typist = newTypist;if (typist != null)typist.addCharacterListener(this);}public synchronized void resetScore() {score = 0;char2type = -1;setScore();}private void setScore() {// This method will be explained later in chapter 7SwingUtilities.invokeLater(new Runnable() {public void run() {setText(Integer.toString(score));}});}private synchronized void newGeneratorCharacter(int c) {if (char2type != -1) {score--;setScore();}char2type = c;}private synchronized void newTypistCharacter(int c) {if (char2type != c) {score--;} else {score++;char2type = -1;}setScore();}public synchronized void newCharacter(CharacterEvent ce) {// Previous character not typed correctly - 1 point penaltyif (ce.source == generator) {newGeneratorCharacter(ce.character);}// If character is extraneous - 1 point penalty// If character does not match - 1 point penaltyelse {newTypistCharacter(ce.character);}}
}

synchronized锁定是可重入的。即当前声明 synchronized的方法中调用此类的其它 synchronized方法时能够直接进入,无需再次获取锁操作。
public int getHoldCount()

查询当前线程保持此锁的次数。 
     对于与解除锁操作不匹配的每一个锁操作。线程都会保持一个锁。

保持计数信息通常仅仅用于測试和调试。比如,假设不应该使用已经保持的锁进入代码的某一部分。则能够声明例如以下:

class X {ReentrantLock lock = new ReentrantLock();// ...     public void m() { assert lock.getHoldCount() == 0;lock.lock();try {// ... method body} finally {lock.unlock();}}
}

返回:
     当前线程保持此锁的次数,假设此锁未被当前线程保持过。则返回 0

十、死锁

死锁会发生在两个或者以上的thread在等待两个或两个以上的lock被释放。且程序的环境却让lock永远无法释放。

十一、Lock公平(Fairness)

使用明白的lock时lock应该怎样被授予?

     1. 让lock应该以先到先服务的原则被授予。
     2. 让它以可以服务最多请求的顺序来被授予。
     3. 锁应该对系统最有利的形式来呗授予。不管它用于什么。(synchronized接近这样的)

版权声明:本文博客原创文章,博客,未经同意,不得转载。

转载于:https://www.cnblogs.com/hrhguanli/p/4746026.html

Java 螺纹第三版 第三章数据同步 读书笔记相关推荐

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

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

  2. python核心编程第3版第1章 正则表达式【读书笔记】

    什么是正则表达式 正则表达式为高级的本文模式匹配.抽取.与/或文本形式的搜索和替换功能提供了基础.简单地说,正则表达式(简称为regex)是一些由字符和特殊符号组成的字符串. re模块 python通 ...

  3. 算法导论第三版第十一章11.1-4

    算法导论第三版第十一章11.1-4 我们希望在一个非常大的数组上,通过利用直接寻址的方式来实现一个字典.开始时,该数组中可能包含一些无用信息,但要堆整个数组进行初始化时不太实际的,因为该数组的规模太大 ...

  4. 《互联网信贷风险与大数据》读书笔记(三)

    第一节 信贷工厂 信贷工厂的起源 起源于淡马锡,信贷工厂模式通过设计标准化产品和流程,实现流水线式的信贷作业过程,并强调全流程的风险管理.发端于中小企业贷款领域,适用于批量化作业的各类信用贷款领域. ...

  5. JAVA高并发程序设计(葛一鸣著)读书笔记

    本文为JAVA高并发程序设计(葛一鸣著)读书笔记.这本书对于刚刚入门的童鞋来讲可能有点深,我推荐可以先看看Java多线程编程核心技术(高洪岩著)一书. 第一章 走入并行世界 什么是同步和异步? 同步就 ...

  6. 《Windows核心编程(第5版•英文版)》暨《深入理解.NET(第2版•英文版)》有奖书评/读书笔记征集活动

    <Windows核心编程(第5版•英文版)>暨<深入理解.NET(第2版•英文版)>有奖书评/读书笔记征集活动 图灵公司自成立以来,得到了CSDN的很多专家和朋友的帮助.为了感 ...

  7. 王爽 汇编语言第三版 第10章 call 和 ret 指令 以及 子程序设计

    第10章 call 和 ret 指令 10.1 ret 和 reft 指令 call 和 ret 指令都是转移指令,他们都修改 IP,或同事修改 CS 和 IP .他们经常被共同来实现子程序的设计. ...

  8. 构建之法 第三版 第3章 部分草稿 (剪牦牛毛、老程序员去金融公司的故事)...

    /* * 这是 <构建之法> 第三版的草稿 */ 3.2 软件工程中的几种思维误区 正如我们在第一章讲的那样,软件有很多特性,软件开发有它自己独特的规律,如果不了解这些特性,软件工程师就会 ...

  9. 机器人学导论(第三版) 第三章 操作臂运动学 3.5操作臂运动学

    机器人学导论(第三版) 学习记录 第三章 操作臂运动学 3.5操作臂运动学 中间坐标系{P},{Q}和{R}的位置 想把坐标系{i}中定义的矢量转化成坐标系{i-1}中的描述,这个变换矩阵可以写成 i ...

最新文章

  1. 我的职业规划是什么呢?什么都要写写画画才行
  2. Java:希望每天叫醒你的不是闹钟而是梦想!
  3. MySQL分区:range(范围)list(in)columns(多字段)hash(散列)key(非数值型的hash)复合(hash key)
  4. java tutorial mobi_Java 初学者List集合教程
  5. 关于JavaScript系列的自学,该怎么学比较好?
  6. 在js中通过location.href方式跳转页面并在路径上传递参数中文乱码解决
  7. python定义一个空的数组_用Python算算你要交多少个人所得税
  8. html5视频播放器 二 (功能实现及播放优化)
  9. JS原生读取 本地 JSON
  10. duet for Mac(Mac投屏软件)好用又不花钱
  11. 某知名系统漏洞挖掘与利用思路探索
  12. 华为员工工资曝光:入职12年月薪31万!手里的窝窝头突然就不香了.....
  13. python建模库介绍:pandas与建模代码的结合,使用Patsy创建模型描述
  14. 支持在线大数据SQL查询平台开源项目
  15. js 数字金额的转换 (转)
  16. poj1015陪审团——DP+路径记录
  17. 百度地图采集员的日常被揭开:人与AI同频的样貌清晰可见
  18. 100集华为HCIE安全培训视频教材整理 | IPSec VdPdN高可靠性案例及配置(三)
  19. C语言版--单链表排序,冒泡排序,选择排序,插入排序,快速排序,应有尽有,保证看懂,没有bug!交换节点版本!
  20. Super Decisions

热门文章

  1. go test 如何输出到控制台_深度剖析 Go 中的 Go 协程 (goroutines) -- Go 的并发
  2. c语言 结构体_颖儿教你学C语言结构体,全面讲解,让程序小白玩转结构体编程...
  3. Linux笔记-为操作系统配ntp服务地址(适用达梦操作系统)
  4. Flask笔记-通过Model访问数据库
  5. 前端笔记-css实现web自适应(当像素小于xx时隐藏此div)
  6. Java工作笔记-AJAX实现整体不变,局部更新(与整体刷新比较)
  7. 中标麒麟安装rpm包命令_在 Fedora 中安装替代版本的 RPM 包
  8. 华为交换机屏蔽远程计算机,华为交换机远程telnet配置的小问题
  9. 336计算机考研怎么做到啊,【图片】2020考研,老学长教你如何规划!【计算机考研吧】_百度贴吧...
  10. vue 刷新echarts_在vue.js中使用echarts,数据动态刷新