锁的简单应用html
用lock来保证原子性(this.count++这段代码称为临界区)java
什么是原子性,就是不可分,从头执行到尾,不能被其余线程同时执行。数组
可经过CAS来实现原子操做this
CAS(Compare and Swap):spa
CAS操做须要输入两个数值,一个旧值(指望操做前的值)和一个新值,在操做期间先比较下旧值有没有发生变化,若是没有发生变化,才交换成新值,发生了变化则不交换。操作系统
CAS主要经过compareAndSwapXXX()方法来实现,而这个方法的实现须要涉及底层的unsafe类.net
unsafe类:java不能直接访问操做系统底层,而是经过本地方法来访问。Unsafe类提供了硬件级别的原子操做线程
这里有个介绍原子操做的博客设计
https://my.oschina.net/xinxingegeya/blog/499223code
还有对unsafe类详解的博客
http://www.cnblogs.com/mickole/articles/3757278.html
1 public class Counter{ 2 private Lock lock = new Lock(); 3 private int count = 0; 4 public int inc(){ 5 lock.lock(); 6 this.count++; 7 lock.unlock(); 8 return count; 9 } 10 }
不可重入锁
先来设计一种锁
1 public class Lock{ 2 private boolean isLocked = false; 3 public synchronized void lock() throws InterruptedException{ 4 while(isLocked){ 5 wait(); 6 } 7 isLocked = true; 8 } 9 public synchronized void unlock(){ 10 isLocked = false; 11 notify(); 12 } 13 }
这实际上是个不可重入锁,举个例子
1 public class Count{ 2 Lock lock = new Lock(); 3 public void print(){ 4 lock.lock(); 5 doAdd(); 6 lock.unlock(); 7 } 8 public void doAdd(){ 9 lock.lock(); 10 //do something 11 lock.unlock(); 12 } 13 }
当调用print()方法时,得到了锁,这时就没法再调用doAdd()方法,这时必须先释放锁才能调用,因此称这种锁为不可重入锁,也叫自旋锁。
可重入锁
设计以下:
1 public class Lock{ 2 boolean isLocked = false; 3 Thread lockedBy = null; 4 int lockedCount = 0; 5 public synchronized void lock() 6 throws InterruptedException{ 7 Thread thread = Thread.currentThread(); 8 while(isLocked && lockedBy != thread){ 9 wait(); 10 } 11 isLocked = true; 12 lockedCount++; 13 lockedBy = thread; 14 } 15 public synchronized void unlock(){ 16 if(Thread.currentThread() == this.lockedBy){ 17 lockedCount--; 18 if(lockedCount == 0){ 19 isLocked = false; 20 notify(); 21 } 22 } 23 } 24 }
相对来讲,可重入就意味着:线程能够进入任何一个它已经拥有的锁所同步着的代码块。
第一个线程执行print()方法,获得了锁,使lockedBy等于当前线程,也就是说,执行的这个方法的线程得到了这个锁,执行add()方法时,一样要先得到锁,因不知足while循环的条件,也就是不等待,继续进行,将此时的lockedCount变量,也就是当前得到锁的数量加一,当释放了全部的锁,才执行notify()。若是在执行这个方法时,有第二个线程想要执行这个方法,由于lockedBy不等于第二个线程,致使这个线程进入了循环,也就是等待,不断执行wait()方法。只有当第一个线程释放了全部的锁,执行了notify()方法,第二个线程才得以跳出循环,继续执行。
这就是可重入锁的特色。
java中经常使用的可重入锁
synchronized
java.util.concurrent.locks.ReentrantLock
ps:顺便记录下java中实现原子操做的类(记录至http://blog.csdn.net/huzhigenlaohu/article/details/51646455)