Java中的锁ReentrantLock,condition 与synchronized,volatile

来源:互联网 发布:才25岁,做程序员就很累 编辑:程序博客网 时间:2024/05/18 14:23

参考文献:

http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html

锁存在的意义在于保证高并发情况下的正确性。

越是粗粒度的锁越容易使用,但性能也越低。

Volatile

  JDK很早就开始支持的锁,锁住的块仅允许一个线程进入。

  Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。

  这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。

  而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。

  使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。

  由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

synchronized

  Volatile仅仅用来修饰变量,以保证变量在多线程运行过程中值不会出现异议。而对于部分代码块,则使用synchronized。

  同样,使用了synchronized的代码块将不会被便以优化过程中调整顺序,且其中变量的值均具有类似volatile关键字的作用。

synchronized的改进

  synchronized的问题也很明显,它仅仅保障了代码块中仅有一个线程在执行。
  
  - 那些等在外面的线程不想等了怎么办?

ReentrantLock

ReentrantLock与Synchronized基本相同,也是最简单的锁。

Condition

用了Lock,那自然要看看Condition,曾经被LinkedBlockingQueue的代码完全搞糊涂了,

    Lock lock = new ReentrantLock();    Condition notfull = lock.newCondition();    Condition notempty = lock.newCondition();    final int nums[] = new int[100];    int cruzer = 0;   public void put(int v) {        lock.lock();        try {            while (cruzer >= nums.length-1)                notempty.await();            nums[cruzer] = v;            cruzer++;            notfull.signal();        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            lock.unlock();        }    }    public Integer get() {        lock.lock();        try {            while ((cruzer-1) <=0)                notfull.await();            int v = nums[cruzer-1];            cruzer--;            notempty.signal();            return v;        } catch (Exception e) {            e.printStackTrace();            return -1;        } finally {            lock.unlock();        }    }

BlockingQueue里的put和take代码类似上例代码,从Lock里做两个condition,然后在lock的保护中进行condition.wait 以及condition.signal

我的疑问就在于,Lock既然是不可重入的,这代码能跑么?上来get卡在condition.wait了之后,后面put进不了lock,怎么会放进去东西然后signal呢?

看看人家JDK的代码注释……

Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to “wait”) until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.wait.

可以理解为当condition.await的时候内部调用了lock.unlock,当condition被再次唤醒时,再次调用lock.lock方法。

这样就很容易理解为啥这个程序能跑了。

下次有空了看看ReentrantLock ReadWriteLock 和他们Condition的代码。

0 0
原创粉丝点击