Java多线程编程中易混淆的3个关键字总结

 更新时间:2015年03月23日 09:22:18   投稿:junjie  
这篇文章主要介绍了Java多线程编程中易混淆的3个关键字总结,本文总结了、volatile、ThreadLocal、synchronized等3个关键字,对这几个容易混淆概念的关键字分别做了讲解,需要的朋友可以参考下

概述

最近在看《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 web自定义filter代码实例

    Java web自定义filter代码实例

    这篇文章主要介绍了Java web自定义filter代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • Spring Boot集成springfox-swagger2构建restful API的方法教程

    Spring Boot集成springfox-swagger2构建restful API的方法教程

    这篇文章主要给大家介绍了关于Spring Boot集成springfox-swagger2构建restful API的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-06-06
  • Java高级特性基础之反射五连问

    Java高级特性基础之反射五连问

    反射赋予了我们在运行时分析类以及执行类中方法的能力。通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。本文就来和大家详细聊聊Java中的反射,感兴趣的可以了解一下
    2023-01-01
  • druid配置数据库连接使用密文密码方式

    druid配置数据库连接使用密文密码方式

    这篇文章主要介绍了druid配置数据库连接使用密文密码方式,具有很好的参考价值,希望对大家有所帮助,
    2023-12-12
  • SpringCloud+Redis实现Api接口限流防止恶意刷接口

    SpringCloud+Redis实现Api接口限流防止恶意刷接口

    接口限流是为了保护系统和服务,防止因为过多的请求而崩溃,本文主要介绍了SpringCloud+Redis实现Api接口限流防止恶意刷接口,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • 详解Java设计模式中的装饰模式

    详解Java设计模式中的装饰模式

    装饰模式是指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。本文将为大家详细介绍一下装饰模式,感兴趣的可以了解一下
    2021-12-12
  • Java多线程编程中线程锁与读写锁的使用示例

    Java多线程编程中线程锁与读写锁的使用示例

    这篇文章主要介绍了Java多线程编程中线程锁与读写锁的使用示例,锁是控制程序多线程并发的重要手段,需要的朋友可以参考下
    2016-04-04
  • Java集合案例之斗地主游戏

    Java集合案例之斗地主游戏

    这篇文章主要为大家详细介绍了Java集合案例之斗地主游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • SpringBoot集成Mybatis-plus并实现自动生成相关文件的示例代码

    SpringBoot集成Mybatis-plus并实现自动生成相关文件的示例代码

    Mybatis-Plus是一个优秀的Mybatis增强工具,目前更新到3.1.1,本文通过示例代码给大家介绍SpringBoot集成Mybatis-plus并实现自动生成相关文件的问题,感兴趣的朋友跟随小编一起看看吧
    2021-12-12
  • IDEA插件之快速删除Java代码中的注释

    IDEA插件之快速删除Java代码中的注释

    这篇文章主要介绍了IDEA插件之快速删除Java代码中的注释,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02

最新评论