Java多线程中易混淆的概念
概述
最近在看《ThinKing In Java》,看到多线程章节时觉得有一些概念比较容易混淆有必要总结一下,虽然都不是新的东西,不过还是蛮重要,很基本的,在开发或阅读源码中经常会遇到,在这里就简单的做个总结。
1.volatile
volatile主要是用来在多线程中同步变量。
在一般情况下,为了提升性能,每个线程在运行时都会将主内存中的变量保存一份在自己的内存中作为变量副本,但是这样就很容易出现多个线程中保存的副本变量不一致,或与主内存的中的变量值不一致的情况。
而当一个变量被volatile修饰后,该变量就不能被缓存到线程的内存中,它会告诉编译器不要进行任何移出读取和写入操作的优化,换句话说就是不允许有不同于“主”内存区域的变量拷贝,所以当该变量有变化时,所有调用该变量的线程都会获得相同的值,这就确保了该变量在应用中的可视性(当一个任务做出了修改在应用中必须是可视的),同时性能也相应的降低了(还是比synchronized高)。
但需要注意volatile只能确保操作的是同一块内存,并不能保证操作的原子性。所以volatile一般用于声明简单类型变量,使得这些变量具有原子性,即一些简单的赋值与返回操作将被确保不中断。但是当该变量的值由自身的上一个决定时,volatile的作用就将失效,这是由volatile关键字的性质所决定的。
所以在volatile时一定要谨慎,千万不要以为用volatile修饰后该变量的所有操作都是原子操作,不再需要synchronized关键字了。
2.ThreadLocal
首先ThreadLocal和本地线程没有一毛钱关系,更不是一个特殊的Thread,它只是一个线程的局部变量(其实就是一个Map),ThreadLocal会为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。这样做其实就是以空间换时间的方式(与synchronized相反),以耗费内存为代价,单大大减少了线程同步(如synchronized)所带来性能消耗以及减少了线程并发控制的复杂度。
个人觉得比较典型的例子就是在Android关于Looper的源码中对ThreadLocal的使用,同时也包含了ThreadLocal的基本用法,具体代码如下:
public class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() will return null unless you've called prepare().
private static final ThreadLocal sThreadLocal = new ThreadLocal();
......
private static Looper mMainLooper = null;
......
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
......
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
......
}
private synchronized static void setMainLooper(Looper looper) {
mMainLooper = looper;
}
public synchronized static final Looper getMainLooper() {
return mMainLooper;
}
......
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
......
}
但需要注意的是,虽然ThreadLocal和Synchonized都用于解决多线程并发访问,ThreadLocal与synchronized还是有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。即Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。所以ThreadLocal并不能代替synchronized,Synchronized的功能范围更广(同步机制)。
3.synchronized
synchronized关键字是Java利用锁的机制自动实现的,一般有同步方法和同步代码块两种使用方式。Java中所有的对象都自动含有单一的锁(也称为监视器),当在对象上调用其任意的synchronized方法时,此对象被加锁(一个任务可以多次获得对象的锁,计数会递增),同时在线程从该方法返回之前,该对象内其他所有要调用类中被标记为synchronized的方法的线程都会被阻塞。当然针对每个类也有一个锁(作为类的Class对象的一部分),所以你懂的.。
最后需要注意的是synchronized是同步机制中最安全的一种方式,其他的任何方式都是有风险的,当然付出的代价也是最大的。
Java多线程中易混淆的概念的更多相关文章
- .NET 中易混淆的概念(Delegate vs Event)
事件(event)是一个非常重要的概念,我们的程序时刻都在触发和接收着各种事件:鼠标点击事件,键盘事件,以及处理操作系统的各种事件.所谓事件就是 由某个对象发出的消息.比如用户按下了某个按钮,某个文件 ...
- JQuery中易混淆的概念
append(): 向每个匹配的元素内部追加内容. <p>I would like to say: </p> $("p").append("< ...
- Java多线程中的竞争条件、锁以及同步的概念
竞争条件 1.竞争条件: 在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象.这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作 ...
- java多线程中并发集合和同步集合有哪些?区别是什么?
java多线程中并发集合和同步集合有哪些? hashmap 是非同步的,故在多线程中是线程不安全的,不过也可以使用 同步类来进行包装: 包装类Collections.synchronizedMap() ...
- java 多线程研究:锁的概念
java多线程:锁 java的多线程中的锁是干嘛的呢?在网上找了很多博客,大都是很专业的语言,让我一时间摸不着头脑.下面分三个部分来总结多线程中的锁的概念. 一,基础概念: 多线程在运行的时候可能会遇 ...
- C#中易混淆的知识点
C#中易混淆的知识点 一.引言 今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为:http://social.msdn.microsoft.com/Forums/zh-CN/52e6 ...
- lua中易混淆函数
lua中易混淆的函数 ipairs和pairs: ipairs只能顺序遍历table,遇到key不是数字就会退出 pairs可以遍历table中所有元素 ----------------------- ...
- java多线程中的三种特性
java多线程中的三种特性 原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并 ...
- JavaScript中易混淆的DOM属性及方法对比
JavaScript中易混淆的DOM属性及方法对比 ParentNode.children VS Node.prototype.childNodes ParentNode.children:该属性继承 ...
随机推荐
- [Locked] Zigzag Iterator
Zigzag Iterator Given two 1d vectors, implement an iterator to return their elements alternately. Fo ...
- centos 安装node js环境
node.js支持多种平台安装,其中Win平台安装比较简单,下面重点讲解下Linux平台的安装步骤.本文以CentOS平台为实例,不准备讲 解采取源码编译安装方式,而是采取在node.js网站下载已经 ...
- JavaScript之作用域与作用域链
今天是2016的第一天,我们得扬帆起航踏上新的征程了.此篇阐述JavaScript中很重要的几个概念:作用域与作用域链及相关知识点. 我们先从变量与作用域的行为关系开始讨论. 变量作用域 JavaSc ...
- 第一节:Scrapy开源框架初探
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 具体开发流程如下: 一.确定待抓取网站 当您需要从某 ...
- 电商H5制作常使用的排版方式
在很多电商网站或者APP中,经常会出现一些精美夺目的活动宣传海报,吸引着用户点击.购买.如今,电商们可以把海报搬到微信中,做出面向用户群大.传播快的H5制作.那么,制作电商H5制作时可以使用哪三种排版 ...
- MongoDB 聚合
聚合操作过程中的数据记录和计算结果返回.聚合操作分组值从多个文档,并可以执行各种操作,分组数据返回单个结果.在SQL COUNT(*)和group by 相当于MongoDB的聚集. aggregat ...
- C++学习路线
已经确定做C++后台的工作了,因此,要对C++要越来越熟悉才行,今天,在此列出学习和温习C++书籍的顺序,从而由浅入深地学习C++. 1. <C++ primer> 2. <Acce ...
- Android开发ScrollView上下左右滑动事件冲突整理一(根据事件)
主要通过重写 onInterceptTouchEvent 事件来解决,代码如下: package com.cm.android.pad.view.itemView; import android.co ...
- PHPMailer中文说明
PHPMailer中文说明 A开头: $AltBody --属性出自:PHPMailer ::$AltBody文件:class.phpmailer .php说明:该属性的设置是在邮件正文不支持HTML ...
- (转)ThinkPHP自定义模板标签详解
转之--http://www.thinkphp.cn/topic/6258.html 模板标签让网站前台开发更加快速和简单,这让本该由程序猿才能完成的工作,现在只要稍懂得HTM的人也能轻易做到,这也就 ...