ReentrantLock与ReadWriteLock的使用

下面的内容基本上来自于《Java并发编程实践》, 留个记录~

 

一, ReentrantLock

ReentrantLock实现了Lock接口,提供了与synchronized 相同的互斥和内存可见性的保证。获得ReentrantLock的锁与进入synchronized 块有着相同的内存语义;释放ReentrantLock锁与退出synchronized块有着相同的内存语义。下面是Lock接口的定义:

 

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;

public interface Lock {
    //获得锁对象,如果无法获得锁,就会阻塞,直到可以获取
    void lock();
    //获得锁对象,能响应中断,如果无法获得锁,并且没有中断事件,线程阻塞
    void lockInterruptibly() throws InterruptedException;
    //如果能获得锁,则返回true;不能获得锁,返回false,不会阻塞
    boolean tryLock();
    //同上,只是增加锁获取超时限制
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    //释放锁
    void unlock();
    
    Condition newCondition();
}

 为什么要创建与内部锁如此相似的机制呢?因为内部锁有一些功能上的限制---不能中断那些正在等待获取锁的线程,并且在请求锁失败的情况下,必须无限等待。但是使用ReentrantLock需要注意的是 锁必须在finally中释放。使用如下:

ReentrantLock lock = new ReentrantLock();
		...
		lock.lock();
		try {
			//code
		} finally {
			lock.unlock();
		}

 具体使用如下:

public class ReentrantLockTest {
	private ReentrantLock lock = new ReentrantLock();
	private SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");

	public void printA() {
		lock.lock();
		System.out.println(format.format(new Date()) + "---printA");
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public void printB() {
		lock.lock();
		System.out.println(format.format(new Date()) + "---printB");
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public static class MyThread extends Thread {
		private ReentrantLockTest reentrantLockTest;
		private String methodName;

		public MyThread(ReentrantLockTest reentrantLockTest, String methodName) {
			super();
			this.reentrantLockTest = reentrantLockTest;
			this.methodName = methodName;
		}

		@Override
		public void run() {
			if ("printA".equalsIgnoreCase(methodName))
				reentrantLockTest.printA();
			else
				reentrantLockTest.printB();
		}
	}
	
	public static void main(String[] args) {
		ReentrantLockTest test = new ReentrantLockTest();
		MyThread t1 = new MyThread(test, "printA");
		MyThread t2 = new MyThread(test, "printB");
		t1.start();
		t2.start();
	}
}

 输出的结果如下:

15:34:34---printA
15:34:37---printB

 

 

二, ReadWriteLock

ReadWriteLock: 允许读操作并发执行;不允许“读/写”, “写/写”并发执行。当数据结构需要频繁的读时,ReadWriteLock相比ReentrantLock与synchronized的性能更好。

public class ReadWriteLockTest {
	private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	private SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
	private Lock readLock = readWriteLock.readLock();
	private Lock writeLock = readWriteLock.writeLock();

	public void read() {
		readLock.lock();
		try {
			System.out.println(format.format(new Date()) + "---read---");
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			readLock.unlock();
		}
	}

	public void write() {
		writeLock.lock();
		try {
			System.out.println(format.format(new Date()) + "---write---");
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			writeLock.unlock();
		}
	}

	public static class MyThread extends Thread {
		private ReadWriteLockTest readWriteLockTest;
		private String methodName;

		public MyThread(ReadWriteLockTest readWriteLockTest, String methodName) {
			super();
			this.readWriteLockTest = readWriteLockTest;
			this.methodName = methodName;
		}

		@Override
		public void run() {
			if ("read".equalsIgnoreCase(methodName))
				readWriteLockTest.read();
			else
				readWriteLockTest.write();
		}
	}

	public static void main(String[] args) {
		ReadWriteLockTest test = new ReadWriteLockTest();
		Thread t1 = new MyThread(test, "read");
		Thread t2 = new MyThread(test, "read");
		t1.start();
		t2.start();
	}
}

 当methodName都为read时,输出结果如下:

15:56:25---read---
15:56:25---read---读取操作同时执行

 

当methodName为read/write时,输出结果如下:

15:57:17---write---
15:57:20---read---

读/写同步执行

你可能感兴趣的:(Java)