Java并发编程进阶上

###1.synchronized 关键字
   1.synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程在执行。
###2.synchronized关键字的使用方式?
   1.修饰实例方法:作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁;
   2.修饰静态方法:就是给当前类加锁,作用于当前类的所有对象,因为访问静态synchronized方法占用的锁是当前类的锁,而访问非静态的synchronized方法占用的锁是当前实例对象的锁。
   3.修饰代码块:指定加锁的对象,对给定的对象加锁,因此要进入该代码块需要获取给定对象的锁。

   4.总结:synchronized关键字加到静态方法和synchronized(class){}代码块是给当前类加锁,而加到非静态方法是给当前对象实例加锁,synchronized(对象){}是给指定的对象进行加锁。尽量不要使用synchronized(String a),因为JVM中,字符串常量池具有缓存的功能
###3.谈谈synchronized和ReentrantLock的区别
   1.它们都是可重入锁,可重入锁的意思:自己可以再次获取自己的内部锁;比如一个线程获取了某个对象的锁,此时这个对象锁还没有被释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,就会造成死锁。同一个线程每次获取锁,锁的计数器都会自增1,所以要等到锁的计数器下降为0时才能释放锁。
   2.synchronized依赖于JVM而ReentrantLock依赖于API。synchronized依赖于JVM的实现,在JDK1.6为synchronized关键字进行了很多的优化,但是这些优化都是在虚拟机层面实现的,并没有直接暴露给我们;而ReentrantLock是JDK层面实现的(也就是API层面,需要lock()和unlock()方法配合try{}finally语句块来完成的),所以我们可以通过看他的源码里来知道其是如何实现的。
   3.相比synchronized来说,ReentrantLock增加了一些高级功能,主要来说有三点,等待可中断;可实现公平锁;可实现选择性通知(锁可以绑定多个条件);
      1.ReentrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制,也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。
      2.ReentrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获取到锁。ReenTrantLock默认情况是非公平的,可以通过ReenTrantLock类的ReenTrantLock(boolean fair)构造方法来制定是否是公平的。
      3.synchronized关键字与wait()和notify()/notifyAll()方法相结合实现等待/通知机制。而ReentrantLock类也可以实现的,但是需要借助于Condition接口与newCondition()方法,Condition是JDK1.5之后才有的,它具有很好的灵活性,比如可以实现多路通知功能也就是在一个Lock对象中可以创建多个Condition实例(即对象监视器),线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。在使用notify()/notifyAll()方法进行通知时,被通知的线程是由JVM选择的,用ReentrantLock类结合Condition实例可以实现选择性通知。这个功能非常重要,而且是在Condition接口中默认提供的,而synchronized关键字就相当于整个Lock对象中只有一个Condition实例,所有的线程都注册在它身上。如果执行notifyAll()方法的话就会通知所有处于等待状态的线程这样会造成很大的效率问题,而Condition实例的signAll()方法只会唤醒注册在该Condition实例中的所有等待线程。
###4.volatile关键字
   1.讲一下Java内存模型:在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别注意的。而在当前Java内存模型下,线程可以把变量保存本地内存,比如机器的寄存器中而不是直接在主存中进行读写,这就可能造成一个线程在主存中修改一个变量的值,而另外一个线程还继续使用它的寄存器中的变量值的拷贝,造成数据的不一致性。
   2.因此,要解决上述的问题,就需要把变量声明为volatile,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取;说白了,volatile关键字的主要作用就是保证变量的可见性(也就是告诉JVM当前变量在寄存器中的值是不确定的,使用前,需要先从主存中读取,因此可以实现可见性。而对n=n+1,n++等操作时,volatile关键字将失效,不能起到像synchronized一样的线程同步(原子性)的效果。),然后还有一个作用是防止指令重排序。
###5.synchronized关键字和volatile关键字的区别
   1.volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好,但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。(synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其他的各种优化之后执行效率有了显著提升,实际开发中使用synchronized关键字的场景还是更多一些。)
   2.多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞。
   3.volatile关键字能保证数据的可见性,但不能保证数据的原子性,synchronized关键都能保证。
   4.volatile关键字主要用于解决变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性。
###6.ThreadLocal简介
   1.通常情况下,我们创建的变量是可以被任何一个线程访问并修改的,如果想实现每一个线程都有自己专属的本地变量该如何进行解决呢?这就使用到了JDK提供的ThreadLocal类。ThreadLocal类主要解决的就是让每一个线程绑定自己的值,可以将ThreadLocal类形象比喻成存放数据的盒子,盒子中可以存储每一个线程的私有数据。
   2.如果你创建了一个ThreadLocal变量,那么访问这个变量的每一线程都会有这个变量的本地副本,这也是ThreadLocal变量名由来,他们可以使用get()和set()方法来获取默认值或者将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
###7.ThreadLocal原理

public class Thread implements Runnable {

//与此线程有关的ThreadLocal值。由ThreadLocal类维护
ThreadLocal.ThreadLocalMap threadLocals = null;

//与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

}
   从源代码中可以看出Thread类中有一个threadLocals和inheritableThreadLocals变量,它们都是ThreadLocalMap类型的变量,我们可以把它们理解成为ThreadLocal类实现的定制化的HashMap。默认这两个变量都是为null,只有当前线程调用ThreadLocal类的set和get方法时才会创建它们,实际上调用这两个方法的时候,我们调用的是ThreadLocalMap类对应的get()和set方法()。
   总结:因此,最终的变量是放在当前线程的ThreadLocalMap中,并不是存在ThreadLocal上,ThreadLocal可以理解为只是ThreadLocalMap的封装,传递了变量值。因为每个Thread中都具备一个ThreadLocalMap,而ThreadLocalMap可以存储以ThreadLocal为key的键值对。这里解释了为什么每个线程访问同一个ThreadLocal得到的确是不同的数值,另外,ThreadLocal是map结构是为了让每个线程可以关联多个ThreadLocal变量。
###8.Java中的引用类型
   1.强引用:当内存不足时,JVM宁可出现OutOfMemeryError错误而使程序终止,也不会回收此对象来释放空间。
   2.软引用:当内存不足的时候,会回收这些对象的内存,用来实现内存敏感的高速缓存。
   3.弱引用:无论内存是否紧张,被垃圾回收器发现立即回收。
   4.虚引用:和没有任何引用一样。
###9.ThreadLocal 内存泄露问题
   ThreadLocalMap中使用的key为ThreadLocal的弱引用,而value是强引用。所以,如果ThreadLocal没有被外部强引用的情况下,在垃圾回收的时候key会被清理掉而value不会。这样一来,ThreadLocalMap中就会出现key为null的Entry,如果我们什么都不做的话,value就永远无法被GC回收,这个时候就可能会产生内存泄漏。
   解决方法:ThreadLocalMap实现中已经考虑了这种情况,在调用set()、get()、remove()方法的时候,会清理掉key为null的记录。保险起见,我们再使用完ThreadLocal方法后最好手动调用remove()方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值