java多线程:Threads and Locks

Threads and Locks

1. Synchronization

        Java编程语言为线程之间的通信提供了多种机制。其中最基本的就是synchronization,通过使用monitors实现的。Java中的每个对象都会关联一个monitor,线程可以锁定或解锁这个monitor。在某一时刻只有一个线程可以锁定monitor。 任何其他线程试图锁定monitor都会被阻塞,直到它们获取该monitor的锁权限。一个线程可能锁定一个特定的monitor多次;每次解锁操作都和锁定操作效果相反。

        同步代码块:Synchronized代码块先计算指定对象的引用;之后再试图对该对象的monitor执行锁定操作,并直到锁定操作成功完成之后才继续执行代码段里的内容。锁定操作完成之后,同步块的主体才被执行。如果同步块的主体已经执行完成,无论是正常结束还是由于异常突然终止,对于当前锁定的monitor的解锁操作将会自动执行。

        同步方法:当Synchronized方法被调用时,它会自动执行锁操作,而且只有当锁操作成功完成之后,方法体才会被执行。如果这个方法是一个实例方法(也就是非static),锁定的monitor是调用此同步方法的实例(也就是this对象)的monitor。如果同步方法是static的,则它锁定的是定义这个static方法的那个Class 对象的monitor(注:对于Class对象的解释请参照http://www.importnew.com/21235.html)。如果方法体已经执行完成,无论是正常结束还是异常终止,对于当前monitor的解锁操作将会自动执行。

        Java编程语言既不能阻止也不需要检测死锁的情况。多个线程拥有(直接或间接)多个对象的锁的程序应该使用传统技术来避免死锁,如有必要,创建不会死锁的更高级锁定原语。

其他机制,例如读写volatile变量和使用java.util.concurrent包中的类,提供了同步读写的替代方式。

 

2. Wait Sets and Notification

        每个对象除了具有相关联的monitor之外,还有相关联的等待组(wait set)。等待组是一组线程。

当一个对象首次被创建时,其等待组为空。基本操作,如向等待组中添加线程和删除线程都是原子的。对于等待组的操作只有通过方法Object.wait,Object.notify和Object.notifyAll。

        等待组的操作也可能受到线程中断状态的影响,并通过Thread类中的方法处理中断。另外,Thread的方法sleep和join特性性派生自Object类中的wait和notify方法。

2.1 Wait

        Wait actions发生在调用wait( )方法,或者wait(long millisecs) 和wait(long millisecs, int nanosecs)。

        NoteA call of wait(long millisecs) with a parameter of zero, or a call of wait(long millisecs, int nanosecs) with two zero parameters, is equivalent to an invocation of wait()

         一个线程如果没有抛出InterruptedException,那就是returns normally

          假设在线程 t 中执行对象m的wait( )方法,而 n 是线程 t 在对象 m 上未被解锁操作匹配的锁定操作的数量。

下列情况之一发生:

  • 如果 n 等于0 ,也就是说线程 t 还没有拥有目标对象 m 的锁,然后会抛出IllegalMonitorStateException。
  • 如果执行的是带时间参数的wait方法,且nanosecs参数范围不在0-999999或者millisecs参数是负的,则会抛出IllegalArgumentException。
  • 如果线程 t 被中断,然后会抛出InterruptedException,并且线程 t 的中断状态被置为false。
  • 否则,发生下列情况
  1. 线程 t 被加到对象 m 的wait set中,并且执行对于 m 的 n 次解锁操作。
  2. 线程 t 不执行任何进一步的指令,直到线程 t 从对象 m 的wait set中移除。下面列出的任何一种操作都可以把线程 t 从对象 m 的wait set中移除,使得线程 t 在一段时间之后恢复运行。                                         
     --对象 m 的notify方法被执行,并且线程 t 被选择从wait set中移除。
     --对象 m的notifyAll方法被执行。
     --对于线程t 执行了interrupt操作。
     --如果是带有时间参数的wait方法,在从执行wait方法开始过了至少millisecs毫秒加上nanosecs纳秒之后,一个内部操作      会把线程 t 从对象 m 的wait set中移除。
     --An internal action by the implementation. Implementations are permitted, although not encouraged,to perform "spurious wake-ups", that is, to remove threads from wait sets and thus enable resumption without    explicit instructions to do so。
  3. 线程 t 在对象 m 上执行 n 次锁操作。
  4. 如果线程 t 在第二步中由于中断从 m 的wait set中移除,然后线程 t 的中断状态置为false,并且wait方法抛出InterruptedException.

 2.2 Notification

  Notification操作在调用方法notify和notifyAll时发生。

假设线程 t 针对目标对象 m 执行以上方法,而 n 是线程 t 在对象 m 上未被解锁操作匹配的锁定操作的数量。下列情况之一将会发生:

  • 如果 n 等于0 ,则抛出IllegalMonitorStateException异常。线程 t 还没有拥有目标对象 m 的锁
  • 如果 n 大于0,且执行的是notify方法,并且对象 m 的wait set不为空,则会选出一个线程从wait set中移除。
  • 如果 n 大于0,且执行的是notifyAll方法,则 m 对象的wait set中的所有线程都将被移除。

猜你喜欢

转载自blog.csdn.net/leftmumu/article/details/79486258