lock与synchronized的关系详解 同步队列 等待队列(二)

本文详细对比了Java中的synchronized关键字与Lock接口在并发控制中的区别,包括它们的工作原理、锁的类型、异常处理、锁的中断、锁的公平性以及条件唤醒等方面。深入探讨了两者的应用场景和优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 synchronized和lock区别

在笔记本:并发编程中讲过一次,现在再补充些新知识:
1.1
synchronized是Java关键字,属于JVM层面;
Lock是api,属于java.util.concurrent.locks.lock

1.2
synchronized底层使用monitorenter、monitorexit,而wait()、notify()也是基于monitor的,所以wait()、notify()需要在synchronized的同步块中使用。
所以为什么Object类的wait()、notify()可以影响线程同步状态。
而lock(如ReentrantLock)是new出来的。

2
synchronized遇到异常也会强制退出,所以synchronized不会死锁。
而lock需要手动解锁,遇到异样不会自动解锁,所以lock使用不当或遇到异常会死锁。(一般lock()写在try上面,unlock()写在finally里面 )

3
尝试进入synchronized的线程不可被中断,除非异常或正常运行完成
尝试通过lock获得锁的线程可以被中断,只要线程是通过lock.tryLock(long time, TimeUnit unit)方法(因为时间一到就会放弃获取锁,从等待队列中移出到哪呢??????  压根不是,看正解:
lock()失败会留在同步队列一直尝试
tryLock()失败就失败,不会留在同步队列再次尝试
tryLock(time, timeUnit)失败的话,一段时间后就也不会留在同步队列再次尝试了
lockInterrupibly()失败,留在同步队列一直尝试,但是可以通过在其他线程内调用 阻塞线程.lockInterrupibly();   ,让阻塞线程提前去争抢一次锁,失败继续留在同步队列一直尝试

boolean succeed = false;
succeed = lock.tryLock(2, TimeUnit.SECONDS);
if (succeed) {

}

 或 lock.lockInterruptibly()方法(当然需要在别的线程中让该等待线程调用interrupt()方法才可让该等待线程被中断)

4
synchronized非公平锁
lock则都可以,通过构造函数的参数来设置,默认非公平锁

5
synchronized不能分组唤醒
ReentrantLock锁可以绑定多个条件condition实现分组唤醒需要唤醒的线程,而不是像synchronized的notify()/notifyAll()那样,要么随机唤醒一个,要么唤醒所有
(Condition condition = new ReentrantLock.newCondition();)
(Condition condition1 = new ReentrantLock.newCondition();)

关于Conditon精确唤醒的例题:
(注意:await()、signal()必须放在lock.lock()、lock.unLock()之间使用!!!!!!!!!否则IllegalMonitorStateException)

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class C20200108 {
    private int number =2;
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();
    public void print5() throws InterruptedException {
        lock.lock();
        while (number!=1){
            c1.await();
        }
        for (int i =0;i<5;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
        number = 2;
        c2.signal();
        lock.unlock();
    }
    public void print10() throws InterruptedException {
        lock.lock();
        while (number!=2){
            c2.await();
        }
        for (int i =0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
        number = 3;
        c3.signal();
        lock.unlock();
    }
    public void print15() throws InterruptedException {
        lock.lock();
        while (number!=3){
            c3.await();
        }
        for (int i =0;i<15;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
        number = 1;
        c1.signal();
        lock.unlock();
    }
    public static void main(String[] args) throws InterruptedException {
        C20200108 c20200108 = new C20200108();
        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    c20200108.print5();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"threadA").start();
//        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    c20200108.print10();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"threadB").start();
  //      TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    c20200108.print15();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"threadC").start();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值