深入浅出Java并发包—锁(Lock)VS同步(synchronized)

深入浅出Java并发包—锁(Lock)VS同步(synchronized)  

2013-05-29 20:51:17|  分类: 并发 |  标签:java  juc  并发    lock  |举报|字号 订阅

 

今天我们来探讨一下Java中的锁机制。前面我们提到,在JDK1.5之前只能通过synchronized关键字来实现同步,这个前面我们已经提到是属于独占锁,性能并不高,因此JDK1.5之后开始借助JNI实现了一套高效的锁实现!

JDK5以后锁的接口是JUC中的Lock,我们来先看一下他的相关API文档。

       深入浅出Java并发包—锁机制(一) - 一线天色 天宇星辰 - 一线天色 天宇星辰

 

方法摘要

 void

lock() 
 
获取锁。 如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。

 void

lockInterruptibly()

         如果当前线程未被中断,则获取锁。

如果锁可用,则获取锁,并立即返回。

如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:

l  锁由当前线程获得;或者

l  其他某个线程中断当前线程,并且支持对锁获取的中断。

如果当前线程:

l  在进入此方法时已经设置了该线程的中断状态;或者

l  在获取锁时被中断,并且支持对锁获取的中断,

则将抛出 InterruptedException,并清除当前线程的已中断状态。

 Condition

newCondition()
         
返回绑定到此 Lock 实例的新 Condition 实例。

在等待条件前,锁必须由当前线程保持。调用 Condition.await() 将在等待前以原子方式释放锁,并在等待返回前重新获取锁。

 boolean

tryLock() 
 
仅在调用时锁为空闲状态才获取该锁。

如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false

 

此方法的典型使用语句如下:

 

      Lock lock = ...;

      if (lock.tryLock()) {

          try {

              // manipulate protected state

          } finally {

              lock.unlock();

          }

      } else {

          // perform alternative actions

      }

 此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。

 boolean

tryLock(long time, TimeUnit unit)
         
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。

如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:

l锁由当前线程获得;或者

l其他某个线程中断当前线程,并且支持对锁获取的中断;或者

l已超过指定的等待时间

 

如果获得了锁,则返回值 true

 

如果当前线程:

l在进入此方法时已经设置了该线程的中断状态;或者

l在获取锁时被中断,并且支持对锁获取的中断,

则将抛出 InterruptedException,并会清除当前线程的已中断状态。

如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。

void

unlock()
          
释放锁。

相对于API来说,我们并不能看出他到底的优点在哪里?我们来看一个实例

package com.yhj.lock;

/**

 * @Described:原子int类型操作测试用例

 * @author YHJ create at 2013-4-26 下午05:58:32

 * @ClassNmae com.yhj.lock.AtomicIntegerTestCase

 */

public interface AtomicIntegerTestCase {

 

    /**

     * ++并返回

     * @return

     * @Author YHJ create at 2013-4-26 下午05:39:47

     */

    int incrementAndGet();

    /**

     * 取值

     * @return

     * @Author YHJ create at 2013-4-26 下午05:39:56

     */

    int get();

}

package com.yhj.lock;

 

 

/**

 * @Described:带同步的测试

 * @author YHJ create at 2013-4-26 下午05:35:35

 * @ClassNmae com.yhj.lock.AtomicIntegerWithLock

 */

public class AtomicIntegerWithSynchronized implementsAtomicIntegerTestCase {

   

    private int value;

    private Object lock  = new Object();//为保证两个方法都在同步内 采用对象同步方法

   

    @Override

    public int incrementAndGet(){

       synchronized(lock){

           return ++value;

       }

    }

   

    @Override

    public int get(){

       synchronized(lock){

           return value;

       }

    }

 

}

package com.yhj.lock;

 

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

/**

 * @Described:带锁的测试

 * @author YHJ create at 2013-4-26 下午05:35:35

 * @ClassNmae com.yhj.lock.AtomicIntegerWithLock

 */

public class AtomicIntegerWithLock implements AtomicIntegerTestCase{

   

    private int value;

    private Lock lock  = new ReentrantLock();

   

    @Override

    public int incrementAndGet(){

       try {

           lock.lock();

           return ++value;

       }finally{

           lock.unlock();

       }

      

    }

 

    @Override

    public int get(){

       try {

           lock.lock();

           return value;

       }finally{

           lock.unlock();

       }

    }

 

}

package com.yhj.lock;

 

public class Client {

 

    /**

     * 启动并等待线程结束

     * @param threads

     * @throws InterruptedException

     * @Author YHJ create at 2013-4-26 下午05:57:16

     */

    private static void startAndWait(Thread [] threads) throwsInterruptedException{

       for(Thread thread:threads)

           thread.start();

       for(Thread thread:threads)

           thread.join();

    }

    /**

     * 准备线程数据

     * @param threads

     * @param testCase

     * @param threadCount

     * @param loopCount

     * @Author YHJ create at 2013-4-26 下午06:01:25

     */

    private static void prepare(Thread [] threads,finalAtomicIntegerTestCase testCase,int threadCount,final int loopCount){

       for (int i = 0; i < threadCount; i++) {

           threads[i] = new Thread(){

              @Override

              public void run() {

                  for(int i=0;i<loopCount;++i){

                     testCase.incrementAndGet();

                  }

              }

           };

       }

    }

 

    public static void main(String[] args) throws InterruptedException {

       //前期数据准备

       final int threadCount = 200;//线程数目

       final int loopCount = 100000;//循环次数

       final AtomicIntegerWithLock lockTestCase = newAtomicIntegerWithLock();//测试对象

       final AtomicIntegerWithSynchronized synchronizedtestCase = newAtomicIntegerWithSynchronized();

       //第一波数据准备

       Thread [] threads= new Thread[threadCount];

       prepare(threads, lockTestCase, threadCount, loopCount);

       //第一波启动

       long costTime = 0;

       long start = System.nanoTime();

       startAndWait(threads);

       long end = System.nanoTime();

       costTime = (end-start);

       //第一波输出

       System.out.println("AtomicIntegerWithLock result:"+lockTestCase.get()+" costTime:"+costTime);

       System.out.println("=======我是分割线=======");

       //第二波数据准备

       threads= new Thread[threadCount];

       prepare(threads, synchronizedtestCase, threadCount, loopCount);

       //第二波启动

       costTime = 0;

       start = System.nanoTime();

       startAndWait(threads);

       end = System.nanoTime();

       costTime = (end-start);

       //第二波输出

       System.out.println("AtomicIntegerWithSynchronized result:"+lockTestCase.get()+" costTime:"+costTime);

    }

 

}

运行结果:

AtomicIntegerWithLock result:20000000 costTime:1192257757

=======我是分割线=======

AtomicIntegerWithSynchronized result:20000000 costTime:3955951264

这个例子很简单,200个线程,每次执行10w++操作,很清楚的大家看到,最好的执行结果都是20000000,都能正常的保证数据的一致性,另外我们还能看到一点,就是Lock消耗的时间要比synchronized少,也证明了Lock的性能是要笔synchronized好的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值