synchronized和lock的异同

在这里插入图片描述

synchronized 和 ReentrantLock 的区别

两者的共同点:

  1. 都是用来协调多线程对共享对象、变量的访问
  2. 都是可重入锁,同一线程可以多次获得同一个锁
  3. 都保证了可见性和互斥性
    两者的不同点:
    用法:ReentrantLock/Lock 是 API /接口级别的, synchronized 是 JVM 级别的,是 Java 中的关键字,内置的语言实现。
    性能
    ReentrantLock 显示的获得、释放锁, synchronized 隐式获得释放锁;ReentrantLock 可响应中断、可轮回, synchronized等待的线程会一直等待下去, 是不可以响应中断的;
    ReentrantLock 可以实现公平锁;
    ReentrantLock 通过 Condition 可以绑定多个条件,进行线程的调度;
    通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到;
    Lock 可以提高多个线程进行读操作的效率,既就是实现读写锁等。
    机制
    synchronized 在发生异常时,会自动释放线程占有的锁,以相反方向释放;因此不会导致死锁现象发生;
    而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁。
    底层实现
    synchronized 是同步阻塞,使用的是悲观并发策略, lock 是同步非阻塞,采用的是乐观并发策略
    运行独立
    最好不要同时使用这两种同步机制,相当于两种不同类型的锁,使用时互不影响

当一个线程进入一个对象的一个synchronized方法后, 其它线程是否可进入此对象的其它方法?

分几种情况:(例子见java程序员面试笔试宝典154)
1.其他方法前是否加了synchronized关键字,如果没加,则能。
2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。
3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。
4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能 同步,因为非静态的方法用的是this。

重入锁(reentrantlock)公平与非公平

非公平
在这里插入图片描述
公平
在这里插入图片描述
释放
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

读写锁

1.写:排他锁。读:共享锁
之前提到锁(如Mutex和ReentrantLock)基本都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞。读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。
除了保证写操作对读操作的可见性以及并发性的提升之外,读写锁能够简化读写交互场景的编程方式。假设在程序中定义一个共享的用作缓存数据结构,它大部分时间提供读服务例如查询和搜索),而写操作占有的时间很少,但是写操作完成之后的更新需要对后续的读服务可见。
2.读写状态的设计
在这里插入图片描述
3.锁降级
锁降级指的是写锁降级成为读锁。如果当前线程拥有写锁,然后将其释放,最后再获取读锁,这种分段完成的过程不能称之为锁降级。锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程。
在这里插入图片描述
RentrantReadWriteLock不支持锁升级(把持读锁、获取写锁,最后释放读锁的过程)。目的也是保证数据可见性,如果读锁已被多个线程获取,其中任意线程成功获取了写锁并更新了数据,则其更新对其他获取到读锁的线程是不可见的。

condition类

await() signal() signalAll()
java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。
相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。
使用 Lock 来获取一个 Condition 对象。

public class AwaitSignalExample {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void before() {
lock.lock();
try {
System.out.println("before");
condition.signalAll();
} finally {lock.unlock();
}
} 
ublic void after() {
lock.lock();
try {
condition.await();
System.out.println("after");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
} 
ublic static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
AwaitSignalExample example = new AwaitSignalExample();
executorService.execute(() -> example.after());
executorService.execute(() -> example.before());
}
efore
after

sleep/wait/yield/join

线程的几种状态以及sleep/wait/yield/join的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值