zoukankan      html  css  js  c++  java
  • 同步锁Synchronized与Lock的区别?

     synchronizedLock两者区别:

      1:Lock是一个接口,而Synchronized关键字

      2:Synchronized会自动释放锁,而Lock必须手动释放锁

      3:Lock可以让等待锁的线程响应中断,而Synchronized不会,线程会一直等待下去。

      4:通过Lock可以知道线程有没有拿到锁,而Synchronized不能。

      5:Lock能提高多个线程读操作的效率。

      6:Synchronized锁住类、方法和代码块,而Lock块范围内

      /**
      * synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
      * lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类
      * 作为对象才能保证锁的生效。
      * 且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
      *
      * synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。
      * 而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低
      * Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,
      * 如果因为冲突失败就重试,直到成功为止。
      * 乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,
      * 会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令
      */

    再看具体代码小例子:

    package com.cn.test.thread.lock;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
     
    public class LockTest {
        private Lock lock = new ReentrantLock();
        /*
         * 使用完毕释放后其他线程才能获取锁
         */
        public void lockTest(Thread thread) {
     
            lock.lock();//获取锁
            try {
                System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称
                Thread.sleep(2000);//为看出执行效果,是线程此处休眠2秒
            catch (Exception e) {
                System.out.println("线程"+thread.getName() + "发生了异常释放锁");
            }finally {
                System.out.println("线程"+thread.getName() + "执行完毕释放锁");
                lock.unlock(); //释放锁
            }
        }
         
        public static void main(String[] args) {
     
            LockTest lockTest = new LockTest();
            //声明一个线程 “线程一”
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    lockTest.lockTest(Thread.currentThread());
                }
            }, "thread1");
            //声明一个线程 “线程二”
            Thread thread2 = new Thread(new Runnable() {
     
                @Override
                public void run() {
                    lockTest.lockTest(Thread.currentThread());
                }
            }, "thread2");
            // 启动2个线程
            thread2.start();
            thread1.start();
     
        }
    }

    执行结果:

     

    package com.cn.test.thread.lock;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockTest {
        private Lock lock = new ReentrantLock();
        
        /*
         * 尝试获取锁 tryLock() 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false
         */
        public void tryLockTest(Thread thread) {
    if(lock.tryLock()) { //尝试获取锁 try { System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称 Thread.sleep(2000);//为看出执行效果,是线程此处休眠2秒 } catch (Exception e) { System.out.println("线程"+thread.getName() + "发生了异常释放锁"); }finally { System.out.println("线程"+thread.getName() + "执行完毕释放锁"); lock.unlock(); //释放锁 } }else{ System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,我无法获取"); } } public static void main(String[] args) {
    LockTest lockTest = new LockTest();  //声明一个线程 “线程一” Thread thread1 = new Thread(new Runnable() { @Override public void run() { lockTest.tryLockTest(Thread.currentThread()); } }, "thread1"); //声明一个线程 “线程二” Thread thread2 = new Thread(new Runnable() { @Override public void run() { lockTest.tryLockTest(Thread.currentThread()); } }, "thread2"); // 启动2个线程 thread2.start(); thread1.start(); } }

    执行结果:

     

    package com.cn.test.thread.lock;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockTest {
        private Lock lock = new ReentrantLock();
    public void tryLockParamTest(Thread thread) throws InterruptedException {
    if(lock.tryLock(3000, TimeUnit.MILLISECONDS)) { //尝试获取锁 获取不到锁,就等3秒,如果3秒后还是获取不到就返回false try { System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称 Thread.sleep(4000);//为看出执行效果,是线程此处休眠2秒 } catch (Exception e) { System.out.println("线程"+thread.getName() + "发生了异常释放锁"); }finally { System.out.println("线程"+thread.getName() + "执行完毕释放锁"); lock.unlock(); //释放锁 } }else{ System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,等待3s后仍无法获取,放弃"); } } public static void main(String[] args) {
    LockTest lockTest = new LockTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { lockTest.tryLockParamTest(Thread.currentThread()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "thread1"); //声明一个线程 “线程二” Thread thread2 = new Thread(new Runnable() { @Override public void run() { try { lockTest.tryLockParamTest(Thread.currentThread()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "thread2"); // 启动2个线程 thread2.start(); thread1.start(); } }

    执行结果:

    因为此时线程1休眠了4秒,线程2等待了3秒还没有获取到就放弃获取锁了,执行结束

    将方法中的 Thread.sleep(4000)改为Thread.sleep(2000)执行结果如下:

    因为此时线程1休眠了2秒,线程2等待了3秒的期间线程1释放了锁,此时线程2获取到锁,线程2就可以执行了

  • 相关阅读:
    Delphi XE4 FireMonkey 开发 IOS APP 发布到 AppStore 最后一步.
    Native iOS Control Delphi XE4
    Delphi XE4 iAD Framework 支持.
    using IOS API with Delphi XE4
    GoF23种设计模式之行为型模式之命令模式
    Android青翼蝠王之ContentProvider
    Android白眉鹰王之BroadcastReceiver
    Android倚天剑之Notification之亮剑IOS
    Android紫衫龙王之Activity
    GoF23种设计模式之行为型模式之访问者模式
  • 原文地址:https://www.cnblogs.com/zhaosq/p/10694597.html
Copyright © 2011-2022 走看看