你真的知道Java同步锁何时释放?

  • 执行线程sleep: 不会释放cpu资源,也不会释放锁资源。

  • 执行wait: 释放cpu资源,也会释放锁资源。


所以总结有:

在Java对象中,有两种池

琐池-----------------------synchronized

等待池---------------------wait(),notify(),notifyAll()

  • 如果一个线程调用了某个对象的wait方法,那么该线程进入到该对象的等待池中(并且已经将锁释放),

  • 如果未来的某一时刻,另外一个线程调用了相同对象的notify方法或者notifyAll方法,

  • 那么该等待池中的线程就会被唤起,然后进入到对象的锁池里面去获得该对象的锁,

  • 如果获得锁成功后,那么该线程就会沿着wait方法之后的路径继续执行。注意是沿着wait方法之后

其他答案:

wait中的线程是不会去竞争对象锁的。 据我所知,开始由于调用了对象的wait方法,线程处于该对象的等待池中,

而后,只有再去调用对象的notifyAll()(唤醒所有等待池中的线程)或者notify()(随机唤醒线程,姑且假设唤醒了我们的那个线程),线程会进入该对象的锁池之中。

锁池中的对象相互竞争对象锁,优先级高的线程竞争得到对象锁的概率高,假若线程没有竞争到,它还是会在锁池之中,唯有线程再次调用wait方法,它才会重新回到等待池中。

java多线程什么时候释放锁—wait()、notify()


由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁:

  • 执行完同步代码块。

    1. 在执行同步代码块的过程中,遇到异常而导致线程终止。
    1. 在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进行对象的等待池。

除了以上情况外,只要持有锁的此案吃还没有执行完同步代码块,就不会释放锁。因此在以下情况下,线程不会释放锁:

  1. 在执行同步代码块的过程中,执行了Thread.sleep()方法,当前线程放弃CPU,开始睡眠,在睡眠中不会释放锁。

  2. 在执行同步代码块的过程中,执行了Thread.yield()方法,当前线程放弃CPU,但不会释放锁。

  3. 在执行同步代码块的过程中,其他线程执行了当前对象的suspend()方法,当前线程被暂停,但不会释放锁。但Thread类的suspend()方法已经被废弃。

避免死锁的一个通用的经验法则是:当几个线程都要访问共享资源A、B和C时,保证使每个线程都按照同样的顺序去访问他们,比如都先访问A,再访问B和C。

  • java.lang.Object类中提供了两个用于线程通信的方法:wait()和notify()。需要注意到是,wait()方法必须放在一个循环中,因为在多线程环境中,共享对象的状态随时可能改变。当一个在对象等待池中的线程被唤醒后,并不一定立即恢复运行,等到这个线程获得了锁及CPU才能继续运行,又可能此时对象的状态已经发生了变化。

  • 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {…} 代码段内。

# 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {…} 代码段内唤醒A。

# 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值