文档章节

Java concurrency in practice笔记 02 03

52iSilence7
 52iSilence7
发布于 2014/06/04 21:22
字数 1064
阅读 35
收藏 0

 什么是线程安全性

        线程安全性的核心是正确性,正确性的含义是如果类的行为与其规范完全一致。因此当多个线程访问某个类时,类的行为始终是安全的,这个类就是线程安全的,这个类也就是一个线程安全类。

        如果一个类没有成员变量,所有的状态都是在线程栈中存储使用的,不会与其他的线程发生数据交互,也就不会出现冲突,这个类是线程安全的。

        如果一个线程要与其他线程共享某个类的变量,这个类需要对共享变量进行同步管理才能保证这个类是线程安全的。

竞态条件(race condition):线程执行结果的正确性取决于执行顺序。

        有check-then-act 和 read-modify-write几种情况,由于操作时非原子性的,这种依赖于以前的结果来进行后续的操作是不安全的,多个线程可能同时check,或有的线程在其他线程check之后act之前对条件进行了修改,就会导致某一次的修改被覆盖,如果用这种方式来生成unique id,就可能导致系统崩溃。

线程安全性有两个方面:原子性和可见性

        上面竞态条件的产生就是因为check-then-act不是原子性操作造成的。可以使用java内置的synchronized关键字加锁,使操作变成原子操作,但是当在有多个共享变量的时候需要注意所有的变量需要持有同一个同步锁,否则会出问题。

        可见性:每个线程执行期间都有自己的线程栈,线程是看不到其他线程的栈内东西的,线程在从主内存读入数据后会在栈内保存一个副本,在线程退出之前会将值写回主内存。这导致的一个问题就是某个线程修改了共享变量的值,另一个线程根据共享变量的值来决定下一步的走向,但是这个线程修改了共享变量的值后对另一个线程是不可见的,这就可能导致另一个线程一直等待。

volatile关键字

        volatile关键字可以保证共享变量的可见性,但不能保证原子性,synchronized关键字两者都能保证。volatile保证线程读到的共享变量的值都是最新的,也就是说volatile修饰的变量是会实时写回主内存中的。volatile提供了比较弱的同步机制,当变量声明为volatile类型后 编译器与运行时会注意到变量是共享的,不会将该变量上的操作与其他内存操作一起重新排序。使用也有限制:对变量的写入操作不能依赖当前值,该变量不会与其他变量一起纳入不变性条件中,在访问变量时不需要加锁。

发布(publish)与逸出(escape)

        发布是指使对象能在当前作用域外的代码中使用,而当 一个不该发布的对象却发布的时候,就产生了逸出。

     下面的get方法就将私有变量泄露出去了,而Secret也被泄露出去,因为可以通过枚举得到每个Secret的实例。  

class Escape{
    private  Set<Secret> set;
    public getSet(){
         return set;
    }
}

        比较难理解的是this逸出,看下面的例子

class ThisEscape{
    ThisEscape(){
       new Thread(new Runnable(){
             public void run(){
                this.s="1";//在类的构造函数还没有完成的时候就调用实例,this就发生了逸出,会产生无                           //法预料的后果
             }
       }).start();
    }
    private String s;
}



        解决办法就是增加一个init()方法,构造函数中只初始化值,不启动线程,需要增加一个内部类和私有变量保存要启动的线程对象。

© 著作权归作者所有

共有 人打赏支持
52iSilence7
粉丝 2
博文 54
码字总数 43221
作品 0
海淀
高级程序员
111 多线程JUC包下代码分析

Java多线程系列目录(共43篇) AtomicLongFieldUpdater:通过反射+CAS实现对传入对象的指定long字段实现类似AtomicLong的操作 http://www.cnblogs.com/skywang12345/p/javathreadscategory.ht...

素雷
2017/10/31
0
0
读《深入理解Java虚拟机》- 笔记08

《深入理解Java虚拟机:JVM高级特性与最佳实践》第2版 第10章 早期(编译期)优化 59. 语法糖 在计算机语言中添加某种语法,对语言的功能没有影响,但是方便开发人员使用。 泛型是一种语法糖...

阿历Ali
08/18
0
0
JAVA区块链项目实战视频课程

课程介绍 全国首套,基于java的区块链实战教程。目的是让更多的java编程者了解区块链,掌握区块链开发。 1、区块链理论:以node.js例子区块链原理有深刻理解; 2、区块链java实战:深刻理解区...

小红牛
09/14
0
0
JNI Kickstart 小结 02 :桥接至与 Java 无关的纯本地库

JNI 程序小结 02 :桥接至与 Java 无关的纯本地库Java + JNI 桥接库 + 纯本地库 异构程序构建示例。 上文: http://my.oschina.net/typhoon/blog/405527 本文为“加强版”。 编写 Java 程序:...

自由狼-台风
2015/06/25
0
1
《虚拟机并发编程》读书笔记(一)

出差北京,趁回杭州之前去了趟海淀,顺手带了本之前一直想买的虚拟机并发编程,虽然这本书在amazon中国上的评价一般,但看看总还是有些收获吧,可能那些说书一般的都是大神吧。书应该是刚上新...

Gaischen
2013/06/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

活动推荐|互联网3.0与区块链新时代论坛(北京)

1 时间地点 **时间:**9月22日 14:00 - 18:00 地点:(北京海淀)西大街70号 3w咖啡 二层 2 活动详情 Harmony创始人Stephen及团队将介绍他们的区块链分片扩容技术。Stephen曾任Apple地图服务...

HiBlock
41分钟前
1
0
如何优雅的删除Redis的大key

关于Redis大键(Key),我们从[空间复杂性]和访问它的[时间复杂度]两个方面来定义大键。前者主要表示Redis键的占用内存大小;后者表示Redis集合数据类型(set/hash/list/sorted set)键,所含有的...

IT--小哥
51分钟前
1
0
spring cloud学习笔记

工具 eclipse 4.9 gradle 4.10.2 spring cloud Finchley.SR1 spring boot 2.0.4 build.gradle buildscript {ext {springBootVersion = '2.0.4.RELEASE'}repositories {jcenter()......

bobby2006
53分钟前
1
0
Tcl命令操作实验-----(5)

Vivado% proc myproc {arg} {puts $arg}Vivado% myproc mynamemynameVivado% if {2>1} {puts 2>1} else {puts 2<1}2>1...

whoisliang
今天
1
0
比特币钱包RPC的PHP调用方法

当我们希望在Php开发的网站中加入比特币支付功能时,需要解决的第一个 问题,就是如何在Php程序代码中调用比特币钱包的RPC API开发接口来实现 我们期望的功能,例如比特币的支付与接收。 例如...

汇智网教程
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部