在测试java多线程中有关 “生产者和消费者” 这个经典问题的时候,写代码测试的时候,思考到一些问题(所以还是要动手,实践才能储真知啊), synchronize 同步锁何时释放,何时获得?重新获得锁资源之后,代码时从哪里开始继续执行的呢?

了解到,锁用到的对象上上面原来有两种池, 1)对象的锁池, 2)对象的等待池。

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

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

-----------------------------------------------------------------------

所以总结有:

在Java对象中,有两种池 
琐池-----------------------synchronized 
等待池---------------------wait(),notify(),notifyAll() 
如果一个线程调用了某个对象的wait方法,那么该线程进入到该对象的等待池中(并且已经将锁释放), 
如果未来的某一时刻,另外一个线程调用了相同对象的notify方法或者notifyAll方法, 
那么该等待池中的线程就会被唤起,然后进入到对象的锁池里面去获得该对象的锁, 
如果获得锁成功后,那么该线程就会沿着wait方法之后的路径继续执行。注意是沿着wait方法之后

其他答案:

wait中的线程是不会去竞争对象锁的。
据我所知,开始由于调用了对象的wait方法,线程处于该对象的等待池中,
而后,只有再去调用对象的notifyAll()(唤醒所有等待池中的线程)或者notify()(随机唤醒线程,姑且假设唤醒了我们的那个线程),线程会进入该对象的锁池之中。
锁池中的对象相互竞争对象锁,优先级高的线程竞争得到对象锁的概率高,假若线程没有竞争到,它还是会在锁池之中,唯有线程再次调用wait方法,它才会重新回到等待池中。 希望对你有帮助。
--------------------------------------

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

由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁:
    1. 执行完同步代码块。
    2. 在执行同步代码块的过程中,遇到异常而导致线程终止。
    3. 在执行同步代码块的过程中,执行了锁所属对象的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锁,才能继续执行。
  
  # 如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
  
  # obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
  
  # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。
  
  wait()/sleep()的区别
  
  前面讲了wait/notify机制,Thread还有一个sleep()静态方法,它也能使线程暂停一段时间。sleep与wait的不同点是:sleep并不释放锁,并且sleep的暂停和wait暂停是不一样的。obj.wait会使线程进入obj对象的等待集合中并等待唤醒。
  
  但是wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException。
  
  如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。
  
  需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出InterruptedException。

Java同步锁何时释放?的更多相关文章

  1. Java同步锁——lock与synchronized 的区别【转】

    在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一.Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchroni ...

  2. Java同步锁全息详解

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  3. java同步锁实现方法

    1.synchronized关键字修饰 当用此关键字修饰方法时,     内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态 synchronized关键字也可以修饰静态方法,此 ...

  4. java 同步锁方法

    方法一:动态同步锁 class Demo_thread implements Runnable{ public static int sum = 0; public synchronized void ...

  5. java同步锁的正确使用

    同步锁分类 对象锁(this) 类锁(类的字节码文件对象即类名.class) 字符串锁(比较特别) 应用场景 在多线程下对共享资源的安全操作. 需求:启动5个线程对共享资源total进行安全操作. 同 ...

  6. JAVA同步锁机制 wait() notify() notifyAll()

    wait() notify() notifyAll() 这3个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块中使用. wait() 必须在synchronized函数或 ...

  7. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  8. Java Learning:并发中的同步锁(synchronized)

    引言 最近一段时间,实验室已经倾巢出动找实习了,博主也凑合了一把,结果有悲有喜,BAT理所应当的跪了,也收到了其他的offer,总的感受是有必要夯实基础啊. 言归正传,最近在看到java多线程的时候, ...

  9. [java多线程] - 锁机制&同步代码块&信号量

    在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同 ...

随机推荐

  1. python基础一 day5 集合

    集合是无序的 增:add()添加进去是无序,不一定是最后面,update()像extend() 删: 没有改,有查,里面的元素是不可变类型 查用for in 交集: 并集: 反交集 叉集: 子集与超集 ...

  2. sleep 和wait的差别

    基本的差别 1.sleep 是Thread 类的方法,wait 是Object类中定义的方法 2.sleep()方法可以在任何地方使用 3.wait()方法只能在synchronized方法中使用,或 ...

  3. 【MyBatis】MyBatis Tomcat JNDI原理及源码分析

    一. Tomcat JNDI JNDI(java nameing and drectory interface),是一组在Java应用中访问命名和服务的API,所谓命名服务,即将对象和名称联系起来,使 ...

  4. mysql在线开启或禁用GTID模式

    在线开启步骤: 1.要求: (1)必须是5.7.6版本以上的mysql (2)GTID状态为OFF 2.开启步骤: (1):SET GLOBAL ENFORCE_GTID_CONSISTENCY = ...

  5. bash实现自动补全

    yum install -y bash-completion source /usr/share/bash-completion/bash_completion 执行后yum拥有选项自动补全功能 对于 ...

  6. MySQL数据库之-foreign key 外键(一对多、多对多、一对一)、修改表、复制表

    摘要: 外键 一对多 外键 多对多 外键 一对一 --------------------------------------------------------------------------- ...

  7. C++实现顺序栈类求解中缀表达式的计算

    控制台第一行打印的数值为使用形如以下方式得到的结果: cout << +*(+)*/- << endl; 即第一个待求解表达式由C++表达式计算所得结果,以用于与实现得出的结果 ...

  8. Java学习之理解递归

    Java支持递归.递归是根据自身定义内容的过程.就Java编程而言,递归是一个允许方法调用自身的特性.调用自身的方法被称为递归.典型的例子就是阶乘的计算,N的阶乘就是从1到N之间所有整数的乘积. 当方 ...

  9. INFO main org.springframework.context.support.AbstractApplicationContext

    原因, spring-framework-5.0.2.RELEASE  需要使用 jdk8.

  10. 66. No EntityManager with actual transaction available for current thread【从零开始学】

    [从零开始学习Spirng Boot-常见异常汇总] 具体异常信息: org.springframework.dao.InvalidDataAccessApiUsageException: No En ...