多线程之深入学习并发编程

本文深入探讨了多线程的基础,包括线程安全的概念、创建线程的常见方式以及wait和sleep的区别。同时,文章详细阐述了synchronized和Lock的异同,以及它们的底层实现原理,强调了线程安全的重要性。此外,还介绍了ThreadLocal的工作原理,并发编程的艺术,如使用CAS避免锁带来的性能问题,以及并发编程的特性,如原子性、可见性和有序性。最后,讨论了线程间的通信和等待唤醒机制在并发控制中的应用。
摘要由CSDN通过智能技术生成

谈到多线程我们就应该知道,在多线程的并发情况下,安全问题和性能问题是我们额外关注的焦点,需要我们不断的选型,技术没有好与不好,只有适不适合,同样在各大公司面试题库中也是必问的,即将走向工作岗位的技术人员应该好好复习和深入理解这方面知识。

1.多线程的基础

1.何为线程安全?

线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。

2.创建线程的四种常见方式
2.1 重写 Thread 类的 run() 方法。
2.2 实现 Runnable 接口,重写 run() 方法。
2.3 实现 Callable 接口,使用 FutureTask 类创建线程
2.4 使用线程池创建、启动线程

3.Runnable接口和Callable接口的区别。
相同点:
1.都是接口,都能够实现多线程编程,都需要Thread.start()来启动线程。

不同点:
1.Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实 现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!
4.wait方法和sleep方法的区别
首先wait方法是Object类中的,而sleep是Thread中的方法,其次调用wait方法会释放掉锁,而调用sleep只是进入睡眠状态,并不会释放掉锁。

2.线程安全和性能问题

实现线程安全主要有以下几种
1.使用synchronized、Lock
一、 synchronized和lock的区别?
1. synchronized是关键字,而Lock是一个接口。
2. synchronized会自动释放锁,而Lock必须手动释放锁。
3. synchronized是不可中断的,Lock可以中断也可以不中断。
4. 通过Lock可以知道线程有没有拿到锁,而synchronized不能。
5. synchronized能锁住方法和代码块,而Lock只能锁住代码块。
6. Lock可以使用读锁提高多线程读效率。
7. synchronized是非公平锁,ReentrantLock可以控制是否是公平锁
二、简述synchronized的底层实现原理?
首先它是一个重量级锁,是需要依赖底层的操作系统的。
当我们使用这个关键字的时候,我们知道无论它作用在哪,都是以对象为锁,java中对象组成部分为:
1.对象头(Mark Word、指向类的指针、数组长度)
2.实例数据
3.对齐填充字节
其中实现的主要都是和对象头中Mark Word有关,它记录了锁的状态,每个对象有一个监视器锁(monitor),当monitor被占用时该对象就会处于锁定状态。线程执行monitorenter指令时尝试获取monitor的所有权,如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者,如果线程已经占有该monitor,只是重新进入,则将monitor的进入数加1.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
monitorexit:
  执行monitorexit的线程必须是monitor对应的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。
2.使用ThreadLocal进行绑定
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
ThreadLocal为每个线程的中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,但大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。
如果想深入理解threadLocal的底层结构和实现原理,推荐
深入理解ThreadLocal

3.并发编程的艺术

在这里插入图片描述
通过上图我们可以知道java内存模型,
主内存
主内存是所有线程都共享的,都能访问的。所有的共享变量都存储于主内存。
工作内存
每一个线程有自己的工作内存,工作内存只存储该线程对共享变量的副本。线程对变量的所有的操作(读,取)都必须在工作内存中完成,而不能直接读写主内存中的变量,不同线程之间也不能直接访问对方工作内存中的变量
这里既然讲到了java内存模型,补充一种实现线程安全的方式,使用CAS(compare and swap)算法,它就是基于java内存模型实现的一种乐观锁并发安全算法
什么是乐观锁与悲观锁?
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样当第二个线程想拿这个数据的时候,第二个线程会一直堵塞,直到第一个释放锁,他拿到锁后才可以访

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值