目录

  1.介绍Lock

  2.Lock的基本使用

  3.Lock之线程之间的通信

  4.总结

 

一、介绍Lock

  首先先讲一下笔者为什么会涉及到Lock这个东西,使用synchronized来锁对象或方法时,如果被锁的这个方法发生阻塞(sleep),那么将影响锁资源的释放,

而其他处于等待状态的对象或方法将一直处于等待状态,直到休眠完或阻塞清除,这就带来了一大并发症。而使用Lock则可以解决这一问题。

  Lock与synchronized之间有很多差异:

  1.Lock是一个接口,synchronized则是java中的一个关键字

  2.Lock需要手动释放锁,synchronized不需要手动释放锁

 

二、Lock的基本使用

  

Lock的API

java选用etcd作为锁 java lock怎么用_java

 

ReentrantLock、ReentrantReadWriteLock.ReadLock、ReentrantReadWriteLock.WriteLock来创建

它主要的方法有:

java选用etcd作为锁 java lock怎么用_java_02

 

ReentrantWriteReadLock是读写锁,它将文件的读和写分开,在这不多做研究。

如想了解的读者请参考

java选用etcd作为锁 java lock怎么用_System_03

 

以下是Lock的基本使用:  

package com.demo.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockThread {
    //创建锁对象
    Lock lock = new ReentrantLock(); 
    
    public void lock(String name) {  
        // 获取锁  
        lock.lock();  
        try {  
            System.out.println(name + "获取锁");  
            // 访问此锁保护的资源  
        } finally {  
            // 释放锁  
            lock.unlock();  
            System.out.println(name + "释放锁");  
        }  
    }  

    public static void main(String[] args) {
        LockThread lt = new LockThread();
        new Thread(() -> lt.lock("A")).start();
        new Thread(() -> lt.lock("B")).start();
    }
}

 

三、Lock之线程之间的通信

  

  如果我们不使用Lock,要做到线程之间的通信我们需要使用到Object类中的wait、notify、notifyAll方法来控制线程间的通信。在jdk1.5当中,线程之间的通信如果使用Lock接口的话需要使用到newCondition方法来创建需要通信的对象Condition。

一下是newCondition方法的具体解释:

java选用etcd作为锁 java lock怎么用_线程间的通信_04

 

Condition对象的方法如下:

java选用etcd作为锁 java lock怎么用_线程间的通信_05

一下是使用condition完成Lock对象线程间的通信Demo:

package com.demo.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Condition初次使用
 * 使用Condition控制线程间的通信
 * @author Administrator
 *
 */
public class ConditionDemo {
    public static void main(String[] args) {
        Output output = new Output();
        for(int i =0;i<2;i++){
        new Thread(new Runnable() {
            public void run() {
                output.get1(1);
            }
        }).start();
        
        new Thread(new Runnable() {
            public void run() {
                output.get2(2);
            }
        }).start();
        
        new Thread(new Runnable() {
            public void run() {
                output.get3(3);
            }
        }).start();
        }
    }
}
class Output{
    private int count =1;
    //创建Lock对象
    final Lock lock = new ReentrantLock();
    //创建三个condition对象
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    
    public void get1(int i){
        //获取锁资源
        lock.lock();
        System.out.println("condition1已获取锁资源");
        try {
            while(count!=1){
                condition1.await();
            }
            System.out.println("condition1获取到资源");
            for(int j=0;j<10;j++){
                System.out.println(i+"正在执行condition1"+j);
                Thread.sleep(1000);
            }
            count++;
            //唤醒第二个等待的线程
            condition2.signal();
        } catch (InterruptedException e) {
                e.printStackTrace();
        }finally{
            //释放锁资源,避免锁死状态
            lock.unlock();
        }
        
    }
    public void get2(int i){
        //获取锁资源
        lock.lock();
        System.out.println("condition2已获取锁资源");
        try {
            while(count!=2){
                condition2.await();
            }
            System.out.println("condition2获取到资源");
            for(int j=0;j<10;j++){
                System.out.println(i+"正在执行condition2"+j);
                Thread.sleep(1000);
            }
            count++;
            //唤醒第三个等待的线程
            condition3.signal();
        } catch (InterruptedException e) {
                e.printStackTrace();
        }finally{
            //释放锁资源,避免锁死状态
            lock.unlock();
        }
        
    }
    public void get3(int i){
        //获取锁资源
        lock.lock();
        System.out.println("condition3已获取锁资源");
        try {
            while(count!=3){
                condition3.await();
            }
            System.out.println("condition3获取到资源");
            for(int j=0;j<10;j++){
                System.out.println(i+"正在执行condition3"+j);
                Thread.sleep(1000);
            }
            count=1;
            //唤醒第一个等待的线程
            condition1.signal();
        } catch (InterruptedException e) {
                e.printStackTrace();
        }finally{
            //释放锁资源,避免锁死状态
            lock.unlock();
        }
        
    }
}

 

 四、总结

 

  结合以上观点来看,总而言之,使用Lock相对于传统使用synchronized关键字来说,逻辑更清晰,避免了线程等待的并发症。而且

我们还可以直观的观测到线程之间或去锁的状态。个人还是推荐是用Lock代替synchronized的。