Java中的Lock接口,比起synchronized,优势在哪里?

如果需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,一次来保证它的完整性,该如何实现?

Lock接口在多线程和并发编程中最大的优势是它们分别为读和写提供了锁。

       读写锁ReentrantReadWriteLock,它表示有两个锁,一个是读操作相关的锁,也称为共享锁;另一个是写操作相关的锁,也叫排他锁。“读写”、“写读”、和 “写写“ 都是互斥的;而 ”读读“ 是异步的,非互斥的。

即:多个线程可以同时进行读取操作,但是同一时刻只允许一个线程进行写入操作。

本题目就可以使用读写锁ReentrantReadWriteLock来实现。

“读读共享”例子:

package com.learn.ReentrantReadWriteLockTest;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读读共享
 */
public class ReadWriteLockTest1 {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        ThreadB b = new ThreadB(service);
        b.setName("B");
        a.start();
        b.start();
    }

}
class Service{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(){
        try{
            lock.readLock().lock();
            System.out.println("获得读锁:"+Thread.currentThread().getName()+" "+System.currentTimeMillis());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.readLock().unlock();
        }
    }
}

class ThreadA extends Thread{
    private Service service;

    public ThreadA(Service service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.read();
    }
}

class ThreadB extends Thread{
    private Service service;

    public ThreadB(Service service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.read();
    }
}

"写写互斥"例子:

package com.learn.ReentrantReadWriteLockTest;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 写写互斥
 */
public class ReadWriteLockTest2 {
    public static void main(String[] args) {
        Service2 service2 = new Service2();
        ThreadA2 a = new ThreadA2(service2);
        a.setName("A");
        ThreadB2 b = new ThreadB2(service2);
        b.setName("B");
        a.start();
        b.start();
    }

}
class Service2{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void write(){
        try{
            lock.writeLock().lock();
            System.out.println("获得写锁:"+Thread.currentThread().getName()+" "+System.currentTimeMillis());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.writeLock().unlock();
        }
    }
}

class ThreadA2 extends Thread{
    private Service2 service;

    public ThreadA2(Service2 service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.write();
    }
}

class ThreadB2 extends Thread{
    private Service2 service;

    public ThreadB2(Service2 service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.write();
    }
}

“读写互斥”例子:

package com.learn.ReentrantReadWriteLockTest;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写互斥
 */
public class ReadWriteLockTest3 {
    public static void main(String[] args) {
        Service3 service3 = new Service3();
        ThreadA3 a = new ThreadA3(service3);
        a.setName("A");
        ThreadB3 b = new ThreadB3(service3);
        b.setName("B");
        b.start();
        a.start();
    }

}
class Service3{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(){
        try{
            lock.readLock().lock();
            System.out.println("获得读锁 "+Thread.currentThread().getName()+" "+System.currentTimeMillis());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.readLock().unlock();
        }
    }

    public void write(){
        try{
            lock.writeLock().lock();
            System.out.println("获得写锁 "+Thread.currentThread().getName()+" "+System.currentTimeMillis());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.writeLock().unlock();
        }
    }
}

class ThreadA3 extends Thread{
    private Service3 service;

    public ThreadA3(Service3 service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.read();
    }
}

class ThreadB3 extends Thread{
    private Service3 service;

    public ThreadB3(Service3 service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.write();
    }
}

“写读互斥”例子:

package com.learn.ReentrantReadWriteLockTest;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写互斥
 */
public class ReadWriteLockTest3 {
    public static void main(String[] args) {
        Service3 service3 = new Service3();
        ThreadA3 a = new ThreadA3(service3);
        a.setName("A");
        ThreadB3 b = new ThreadB3(service3);
        b.setName("B");
        b.start();
        a.start();
    }

}
class Service3{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(){
        try{
            lock.readLock().lock();
            System.out.println("获得读锁 "+Thread.currentThread().getName()+" "+System.currentTimeMillis());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.readLock().unlock();
        }
    }

    public void write(){
        try{
            lock.writeLock().lock();
            System.out.println("获得写锁 "+Thread.currentThread().getName()+" "+System.currentTimeMillis());
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.writeLock().unlock();
        }
    }
}

class ThreadA3 extends Thread{
    private Service3 service;

    public ThreadA3(Service3 service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.read();
    }
}

class ThreadB3 extends Thread{
    private Service3 service;

    public ThreadB3(Service3 service){
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.write();
    }
}

如果需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,一次来保证它的完整性,该如何实现?代码如下:

package com.learn.ReentrantReadWriteLockTest;

import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockTest5 {
    public static void main(String[] args) {
        ReadWrite readWrite = new ReadWrite();
        //创建3个写线程
        for (int i=0;i<3;i++){
            ThreadWrite write = new ThreadWrite(readWrite,new Random().nextInt(100));
            write.setName("write"+i+":");
            write.start();
        }
        //创建3个读线程
        for (int i=0;i<3;i++){
            ThreadRead read = new ThreadRead(readWrite);
            read.setName("read"+i+":");
            read.start();
        }

    }
}

class ReadWrite{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Object data=null;
    public void read(){
        try{
            lock.readLock().lock();
            try {
                System.out.println(Thread.currentThread().getName()+"is ready to read");
                Thread.sleep(new Random().nextInt(100));
                System.out.println(Thread.currentThread().getName()+"have read date "+data);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.readLock().unlock();
        }
    }

    public void write(Object data){
        try{
            lock.writeLock().lock();
            try {
                System.out.println(Thread.currentThread().getName()+"is ready to write");
                this.data = data;
                Thread.sleep(new Random().nextInt(100));
                System.out.println(Thread.currentThread().getName()+"have write date "+data);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally{
            lock.writeLock().unlock();
        }
    }
}

class ThreadRead extends Thread{
    private ReadWrite readWrite;

    public ThreadRead(ReadWrite readWrite){
        this.readWrite = readWrite;
    }

    @Override
    public void run() {
        super.run();
        //while(true){
            readWrite.read();
        //}

    }
}

class ThreadWrite extends Thread{
    private ReadWrite readWrite;
    private Object data;


    public ThreadWrite(ReadWrite readWrite,Object data){
        this.readWrite = readWrite;
        this.data = data;
    }

    @Override
    public void run() {
        super.run();
        //while(true){
            readWrite.write(data);
        //}
    }
}


  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值