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();
    }
}

Java中的Lock接口,比起synchronized,优势在哪里?_第1张图片

"写写互斥"例子:

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();
    }
}

Java中的Lock接口,比起synchronized,优势在哪里?_第2张图片

“读写互斥”例子:

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();
    }
}

Java中的Lock接口,比起synchronized,优势在哪里?_第3张图片

“写读互斥”例子:

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();
    }
}

Java中的Lock接口,比起synchronized,优势在哪里?_第4张图片

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

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);
        //}
    }
}


Java中的Lock接口,比起synchronized,优势在哪里?_第5张图片

你可能感兴趣的:(java)