lock

作者: test_java | 来源:发表于2019-05-09 13:32 被阅读0次

    并发编程领域,有两大核心问题:

    一个是互斥,即同一时刻只允许一个线程访问共享资源;
    另一个是同步,即线程之间如何通信、协作。这两大问题,管程都是能够解决的。

    Java SDK并发包通过Lock和Condition两个接口来实现管程,

    其中Lock用于解决互斥问题,
    Condition用于解决同步问题。

    Lock 使用

    synchronized申请资源的时候,如果申请不到,线程直接进入阻塞状态了,而线程进入阻塞状态,啥都干不了,也释放不了线程已经占有的资源。但我们希望的是:

    对于“不可抢占”这个条件,占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源,这样不可抢占这个条件就破坏掉了。
    如果我们重新设计一把互斥锁去解决这个问题,那该怎么设计呢?我觉得有三种方案。

    1.能够响应中断。synchronized的问题是,持有锁A后,如果尝试获取锁B失败,那么线程就进入阻塞状态,一旦发生死锁,就没有任何机会来唤醒阻塞的线程。但如果阻塞状态的线程能够响应中断信号,也就是说当我们给阻塞的线程发送中断信号的时候,能够唤醒它,那它就有机会释放曾经持有的锁A。这样就破坏了不可抢占条件了。

    2.支持超时。如果线程在一段时间之内没有获取到锁,不是进入阻塞状态,而是返回一个错误,那这个线程也有机会释放曾经持有的锁。这样也能破坏不可抢占条件。

    3.非阻塞地获取锁。如果尝试获取锁失败,并不进入阻塞状态,而是直接返回,那这个线程也有机会释放曾经持有的锁。这样也能破坏不可抢占条件。

    创建的锁的具体类名是ReentrantLock,这个翻译过来叫可重入锁,这个概念前面我们一直没有介绍过。所谓可重入锁,顾名思义,指的是线程可以重复获取同一把锁。例如下面代码中,当线程T1执行到 ① 处时,已经获取到了锁 rtl ,当在 ① 处调用 get()方法时,会在 ② 再次对锁 rtl 执行加锁操作。此时,如果锁 rtl 是可重入的,那么线程T1可以再次加锁成功;如果锁 rtl 是不可重入的,那么线程T1此时会被阻塞。

    除了可重入锁,可能你还听说过可重入函数,可重入函数怎么理解呢?指的是线程可以重复调用?显然不是,所谓可重入函数,指的是多个线程可以同时调用该函数,每个线程都能得到正确结果;同时在一个线程内支持线程切换,无论被切换多少次,结果都是正确的。多线程可以同时执行,还支持线程切换,这意味着什么呢?线程安全啊。所以,可重入函数是线程安全的。

    在使用ReentrantLock的时候,你会发现ReentrantLock这个类有两个构造函数,一个是无参构造函数,一个是传入fair参数的构造函数。fair参数代表的是锁的公平策略,如果传入true就表示需要构造一个公平锁,反之则表示要构造一个非公平锁。

    锁的最好的实际
    永远只在更新对象的成员变量时加锁
    永远只在访问可变的成员变量时加锁
    永远不在调用其他对象的方法时加锁

    class Account {
      private int balance;
      private final Lock lock
              = new ReentrantLock();
      // 转账
      void transfer(Account tar, int amt){
        while (true) {
          if(this.lock.tryLock()) {
            try {
              if (tar.lock.tryLock()) {
                try {
                  this.balance -= amt;
                  tar.balance += amt;
                } finally {
                  tar.lock.unlock();
                }
              }//if
            } finally {
              this.lock.unlock();
            }
          }//if
        }//while
      }//transfer
    }
    

    会不会导致死锁
    有可能活锁,A,B两账户相互转账,各自持有自己lock的锁,都一直在尝试获取对方的锁,形成了活锁

    能够响应中断, 支持超时 、非阻塞的获取锁

    相关文章

      网友评论

          本文标题:lock

          本文链接:https://www.haomeiwen.com/subject/vmlwoqtx.html