2_Synchronized和Lock
Posted root_zhb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2_Synchronized和Lock相关的知识,希望对你有一定的参考价值。
Synchronized和Lock
1、多线程编程步骤
- 创建资源类,在资源类中创建属性和方法
- 在资源类操作方法
- 判断
- 干活
- 通知
- 创建多个线程,调用资源类的操作方法
- 防止虚假唤醒问题
2、Synchronized
2.1、Synchronized作用范围
- 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
- 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
- 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
- 修饰一个类,其作用的范围是 synchronized 后面括号括起来的部分,作用的对象是这个类的所有对象。
2.2、Synchronized实现卖票例子
class Ticket {
//票数
private int number = 30;
//操作方法:卖票
public synchronized void sale() {
//判断:是否有票
if(number > 0) {
System.out.println(Thread.currentThread().getName()+" : "+(number--)+" "+number);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
Ticket ticket=new Ticket();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.sale();
}
},"AA").start();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.sale();
}
},"BB").start();
new Thread(()->{
for(int i=0;i<40;i++){
ticket.sale();
}
},"CC").start();
}
}
3、Lock
3.1、Lock简介
-
Lock接口的所有实现类
- 可重入锁(普通锁) :ReentrantLock
- 读锁:ReentrantReadWriteLock.ReadLock
- 写锁:ReentrantReadWriteLock.WriteLock
-
Lock用法
// 以可重入锁为例 Lock lock = new ReentrantLock(); // 加锁 lock.lock(); try{ // 业务代码 }catch(){ }finally{ // 解锁 lock.unlock(); }
-
ReentrantLock构造方法
//默认非公平锁 public ReentrantLock() { sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
-
非公平锁和公平锁
- 公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。(先来后到)
- 非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。()
3.2、Lock卖票
class Ticket {
//票数
private int number = 30;
//创建可重入锁
private final ReentrantLock lock =new ReentrantLock();
//操作方法:卖票
public synchronized void sale() {
//上锁
lock.lock();
try {
//判断:是否有票
if(number > 0) {
System.out.println(Thread.currentThread().getName()+" : "+(number--)+" "+number);
}
}finally {
lock.unlock();
}
}
}
4、Lock和Synchronized对比
-
Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言实现;
-
synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;
Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁; -
Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用synchronized 时,等待的线程会一直等待下去,不能够响应中断
-
通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
-
Lock 可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时 Lock 的性能要远远优于synchronized。
以上是关于2_Synchronized和Lock的主要内容,如果未能解决你的问题,请参考以下文章