基本概念
- 当多个线程同时访问同一种昧享资源时,可能会造成数据的覆盖等不一致性问题,此时就需要对线程之间进行通信和协调,该机制就叫做线程的同步机制。
- 多个线程并发读写同一个临界资源时会发生线程并发安全问题。
- 异步操作:多线程并发的操作,各自独立运行。
- 同步操作:多线程串行的操作,先后执行的顺序。
解决方案
- 由程序结果可知:当两个线程同时对同一个账户进行取款时,导致最终的账户余额不合理。
- 引发原因:线程一执行取款时还没来得及将取款后的余额写入后台,线程二就已经开始取款。
- 解决方案:让线程一执行完毕取款操作后,再让线程二执行即可,将线程的并发操作改为串行操作。
- 经验分享:在以后的开发尽量减少串行操作的范围,从而提高效率。
实现方式
-
在Java语言中使用 synchronized 关键字来实现同步/对象锁机制从而保证线程执行的原子性,具体方式如下:
-
使用同步代码块的方式实现部分代码的锁定,格式如下:
synchronized (类类型的引用){
// 类类型的引用必须是一个对象 否则无法锁住
编写所有需要锁定的代码
}实现 Runnable 类
-
使用同步方法的方式实现所有代码的锁定。
直接使用 synchronized关键字来修饰整个方法即可
该方式等价于:
synchronized(this){整个方法体的代码}
基本概念
- 从Java5开始提供了更强大的线程同步机制一使用显式定义的同步锁对象来实
-
java.util.concurrent.locks.Lock
接口是控制多个线程对共享资源进行访问的工具。 - 该接口的主要实现类是 Reentrantlock类,该类拥有与 synchronized相同的并发性,在以后的线程安全控制中,经常使用 Reentrantlock类显式加锁和释放锁。
常用的方法
方法声明 | 功能介绍 |
---|---|
Reentrantlock() | 使用无参方式构造对象 |
void lock | 获取锁 |
void unlock | 释放锁 |
与 synchronized方式的比较
- Lock是显式锁,需要手动实现开启和关闭操作,而 synchronized是隐式锁,执行锁定代码后自动释放。
- Lock 只有同步代码块方式的锁,而 synchronized有同步代码块方式和同步方法两种锁。
- 使用 Lock 锁方式时,Java虛拟机将花费较少的时间来调度线程,因此性能更好。
方法声明 | 功能介绍 |
---|---|
void wait() | 用于使得线程进入等待状态,直到其它线程调用 notify()或notifyAll()方法 |
void wait(long timeout) | 用于进入等待状态,直到其它线程调用方法或参数指定的毫秒数已经过去为止 |
void notify() | 60用于唤等待的单个线程 |
void notifyAll() | 用于唤酲等待的所有线程 |