聊一聊Java中的lock锁

在Java多线程中,可以使用关键字Synchronized实现线程之间互斥。在JDK1.5之后,提供了线程并发库java.util.concurrent用于操作多线程,其中包含了java.util.concurrent.atomic和java.util.concurrent.lock。atomic可以实现数据或变量的原子性操作,而lock可以实现线程互斥,可以实现读写锁,跟Synchronized一样同属于可重入锁,但在使用上比Synchronized更加灵活。

在代码中,可以通过new ReentrantLock()创建一个lock锁,调用lock()实现对代码上锁,调用unlock()可以解锁。当然,为了保证代码运行出现异常时也能解锁,应该把上锁的代码用try包裹起来,并在finally里解锁,具体代码实现如下:

public class Main {
    //静态内部类实现线程共享
    static class Example{
        //创建lock
        Lock lock = new ReentrantLock();
        public void outPut(String str){
            //上锁
            lock.lock();
            try{
                for(int i=0;i<str.length();i++){
                    System.out.print(str.charAt(i));
                }
                System.out.print("\n");
            }finally {
                //解锁
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        final Example example = new Example();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    example.outPut("str1");
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    example.outPut("str2");
                }
            }
        }).start();
    }
}

对于lock的读写锁,可以通过new ReentrantReadWriteLock()获取到一个读写锁。所谓读写锁,便是多线程之间读不互斥,读写互斥。读写锁是一种自旋锁,如果当前没有读者,也没有写者,那么写者可以立刻获得锁,否则它必须自旋在那里,直到没有任何写者或读者。如果当前没有写者,那么读者可以立即获得该读写锁,否则读者必须自旋在那里,直到写者释放该锁。具体代码实现如下:

public class Main {
    //静态内部类实现线程共享
    static class Example{
        //创建lock
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        //读操作
        public void read(){
            //获取读锁并上锁
            lock.readLock().lock();
            try{
                System.out.println("读线程开始");
                Thread.sleep(1000);
                System.out.println("读线程结束");
            }catch (Exception e){
                e.printStackTrace();
            }finally{
                //解锁
                lock.readLock().unlock();
            }
        }
        //写操作
        public void write(){
            //获取写锁并上锁
            lock.writeLock().lock();
            try{
                System.out.println("写线程开始");
                Thread.sleep(1000);
                System.out.println("写线程结束");
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                //解锁
                lock.writeLock().unlock();
            }
        }
    }

    public static void main(String[] args) {
        final Example example = new Example();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    example.read();
                    example.write();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    example.read();
                    example.write();
                }
            }
        }).start();
    }
}

运行结果:


根据结果可以发现,多线程下ReentrantReadWriteLock可以多线程同时读,但写的话同一时刻只有一个线程执行。

最后说一说读写锁的应用场景,我们可以利用读写锁可是实现一个多线程下数据缓存的功能,具体实现思路如下:

class dataCatch{
    Object data; //缓存的数据
    public volatile Boolean isCatch = false; //是否有缓存
    ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); //生成读写锁

    public void process(){
        lock.readLock().lock(); //先加读锁,此时数据不会被修改
        //数据没有缓存
        if(!isCatch){
            lock.readLock().unlock(); //解读锁
            lock.writeLock().lock(); //加写锁,此时数据不会被读到
            /********
             *
             * 执行数据查询操作并赋值给data
             *
             ********/
            isCatch = true;
            lock.readLock().lock();  //先加读锁后解写锁
            lock.writeLock().lock();
        }
        /********
         *
         * 放回data数据给用户
         *
         ********/
        lock.readLock().unlock(); //解读锁
    }
}

猜你喜欢

转载自blog.csdn.net/hsf15768615284/article/details/80044368