Chinaunix首页 | 论坛 | 博客
  • 博客访问: 80446
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 340
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-02 20:25
文章分类

全部博文(31)

文章存档

2015年(2)

2014年(29)

我的朋友

分类: Java

2014-09-05 15:43:06

  在JDK1.6之前Java内置的synchronized关键字是有操作系统内置的互斥锁实现,而获取互斥锁需要系统调用,系统调用又是个费时的操作,所以JDK1.5中的synchronized比起并发包中Lock性能要差不少。到了1.6引入了偏向锁、轻量级锁、自适应自旋锁等对synchronized进行了优化,从而让synchronized的性能得到了极大的提高,已经不亚于Lock了。

1. 自旋锁

   自旋锁相对是传统上的阻塞锁。阻塞锁在线程不能获取锁的情况下,通过系统调用将线程阻塞。而自旋锁则不同,它不阻塞线程,只是让线程继续持有CPU做一些空操作而已。很明显,自旋锁在单CPU系统下是无效的。如果线程等待锁的时间很短,那么自旋锁无疑具有更好的性能,因为它没有上下文切换,但是如果线程等待锁的时间比较长,那么自旋就会造成CPU资源的浪费。到底选择自旋还是阻塞取决于锁的等待时间,但这又难以考量,所以引入了自适应自旋锁,根据这个锁的统计量来选择自旋的时间,超过这个时间自动进入阻塞。

2. 偏向锁

  java中正规的偏向锁貌似是这样,指第一个获取锁的线程,如果这个线程再次请求锁,不需要同步,但是一旦有其他线程尝试申请该锁,不管成功与失败,则该锁都不再是偏向锁。这是种在无竞争环境下对锁的优化,一旦出现竞争,立马失去偏向功能。而在ReentrantLock中,当一个锁被一个线程持有时,如果这个线程再次申请锁,则可以不需要任何同步操作进可以获取该锁。两者虽有少许差别,但想要到达的目的都差不多。在ReentrantLock的实现:

点击(此处)折叠或打开

  1. final boolean nonfairTryAcquire(int acquires) {
  2.             final Thread current = Thread.currentThread();
  3.             int c = getState();
  4.             if (c == 0) {
  5.                 if (compareAndSetState(0, acquires)) {
  6.                     setExclusiveOwnerThread(current);
  7.                     return true;
  8.                 }
  9.             }
  10.             else if (current == getExclusiveOwnerThread()) {
  11.                 int nextc = c + acquires;
  12.                 if (nextc < 0) // overflow
  13.                     throw new Error("Maximum lock count exceeded");
  14.                 setState(nextc);
  15.                 return true;
  16.             }
  17.             return false;
  18.         }
在这里,当一个已获取锁的线程再次申请锁的时候,很显然没有使用任何同步操作。

3. 轻量锁

 轻量级锁是相对于之前的普通互斥锁的,而轻量级锁被引入后,原来的普通锁则成为重量级锁。所以,轻量级锁的本质,避免使用操作系统的互斥调用,仅通过CAS来获取锁。当一个线程通过CAS获取锁后,则这个锁为轻量级锁。如果此时另外一个线程试图获取该锁,则锁升级为重量锁,该线程被阻塞。在ReentrantLock中实现就是如此,但ReentrantLock中的锁并没有什么轻量级锁重量级锁之分,获取一个空闲的锁仅需要CAS,可以认为此时是轻量级锁,获取一个非空闲锁,则线程需要阻塞,此时可以认为该锁为重量级锁。
  事实上,ReentrantLock在1.5中比synchronized性能要高不少,在1.6中synchronized虽然经过优化,引入偏向锁,轻量级锁等概念,但性能并没有比ReentrantLock高。但synchronized在功能适用的情况下,仍然是第一选择。
 JDK中偏向锁跟轻量级锁适用于带有同步代码但无竞争的程序。

阅读(863) | 评论(0) | 转发(0) |
0

上一篇:7. 线程池

下一篇:1. 地址与Socket

给主人留下些什么吧!~~