spring|Java程序员必会的三个技能: Spring+MySQL+并发编程( 三 )


(2)如果你不这么做 , 你的代码会抛出 IllegalMonitorStateException 异常 。
(3)还有一个原因是为了避免 wait 和 notify 之间产生竞态条件 。
wait()方法强制当前线程释放对象锁 。 这意味着在调用某对象的 wait()方法之前 , 当前线程必须已经获得该对象的锁 。 因此 , 线程必须在某个对象的同步方法或同步代码块中才能调用该对象的 wait()方法 。
在调用对象的 notify()和 notifyAll()方法之前 , 调用线程必须已经得到该对象的锁 。 因此 , 必须在某个对象的同步方法或同步代码块中才能调用该对象的 notify()或 notifyAll()方法 。
调用 wait()方法的原因通常是 , 调用线程希望某个特殊的状态(或变量)被设置之后再继续执行 。 调用 notify()或 notifyAll()方法的原因通常是 , 调用线程希望告诉其他等待中的线程:“特殊状态已经被设置” 。 这个状态作为线程间通信的通道 , 它必须是一个可变的共享状态(或变量) 。
9、Java 中 interrupted 和 isInterruptedd 方法的区别?
interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会 。 Java 多线程的中断机制是用内部标识来实现的 , 调用 Thread.interrupt()来中断一个线程就会设置中断标识为 true 。 当中断线程调用静态方法 Thread.interrupted()来检查中断状态时 , 中断状态会被清零 。 而非静态方法 isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识 。 简单的说就是任何抛出 InterruptedException 异常的方法都会将中断状态清零 。 无论如何 , 一个线程的中断状态有有可能被其它线程调用中断来改变 。
10、Java 中 synchronized 和 ReentrantLock 有什么不同?
相似点:
这两种同步方式有很多相似之处 , 它们都是加锁方式同步 , 而且都是阻塞式的同步 , 也就是说当如果一个线程获得了对象锁 , 进入了同步块 , 其他访问该同步块的线程都必须阻塞在同步块外面等待 , 而进行线程阻塞和唤醒的代价是比较高的 。
区别:
这两种方式最大区别就是对于 Synchronized 来说 , 它是 java 语言的关键字 , 是原生语法层面的互斥 , 需要 jvm 实现 。 而 ReentrantLock 它是 JDK 1.5 之后提供的 API 层面的互斥锁 , 需要 lock()和 unlock()方法配合 try/?nally 语句块来完成 。
Synchronized 进过编译 , 会在同步块的前后分别形成 monitorenter 和 monitorexit 这个两个字节码指令 。 在执行 monitorenter 指令时 , 首先要尝试获取对象锁 。 如果这个对象没被锁定 , 或者当前线程已经拥有了那个对象锁 , 把锁的计算器加 1 , 相应的 , 在执行 monitorexit 指令时会将锁计算器就减 1 , 当计算器为 0 时 , 锁就被释放了 。 如果获取对象锁失败 , 那当前线程就要阻塞 , 直到对象锁被另一个线程释放为止 。
由于 ReentrantLock 是 java.util.concurrent 包下提供的一套互斥锁 , 相比 Synchronized , ReentrantLock 类提供了一些高级功能 , 主要有以下 3 项:
(1)等待可中断 , 持有锁的线程长期不释放的时候 , 正在等待的线程可以选择放弃等待 , 这相当于 Synchronized 来说可以避免出现死锁的情况 。
(2)公平锁 , 多个线程等待同一个锁时 , 必须按照申请锁的时间顺序获得锁 , Synchronized 锁非公平锁 , ReentrantLock 默认的构造函数是创建的非公平锁 , 可以通过参数 true 设为公平锁 , 但公平锁表现的性能不是很好 。
(3)锁绑定多个条件 , 一个 ReentrantLock 对象可以同时绑定对个对象 。
二、MySQL

1.Mysql 中有哪几种锁?
(1)表级锁:开销小 , 加锁快 。 不会出现死锁 , 锁定粒度大 , 发生锁冲突的概率高 , 并发度低 。
(2)行级锁:开销大 , 加锁慢 。 会出现死锁 , 锁定粒度小 , 发生锁冲突的概率低 , 并发度高 。


推荐阅读