JDK并发包

同步控制:

重入锁:synchronized的功能扩展
java.util.concurrent.locks.ReentrantLock

ReentrantLock的几个重要方法如下:
lock():获得锁,如果锁已被占用,则等待
lockInterruptibly():获得锁,但优先响应中断
tryLock():尝试获得锁,如果成功,返回true,失败返回false。该方法不等待,立即返回
tryLock(long time, TimeUnit unit):在给定时间内尝试获得锁
unlock():释放锁

在重入锁的实现中,主要包含三个要素:
1.原子状态。原子状态使用CAS操作来存储当前锁的状态,判断锁是否已经被别的线程持有
2.等待队列。所有没有请求到锁的线程,会进入等待队列进行等待。待有线程释放锁后,系统就能从等待队列中唤醒一个线程,继续工作
3.阻塞原语park()和unpark(),用来挂起和恢复线程。没有得到锁的线程将会被挂起(有关park()和unpark()方法的介绍,见LockSupport线程阻塞工具类)

重入锁的搭档:Condition条件
Condition接口的基本方法如下:
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
上述方法含义如下:
await()方法会使当前线程等待,同时释放当前锁,当其他线程中使用signal()或signalAll()方法时,线程会重新获得锁并继续执行。或者当线程被中断时,也能跳出等待。和Object.wait()方法相似。
awaitUninterruptibly()方法与await()方法基本相同,但是它不会在等待过程中响应中断。
singal()方法用户唤醒一个在等待中的线程,singnalAll()方法会唤醒所有等待中的线程。

信号量(Semaphore):
信号量是对锁的扩展,为多线程协作提供了更为强大的控制方法。无论是内部锁(synchronized)还是重入锁(ReentrantLock),一次都只允许一个线程访问一个资源,而信号量却可以指定多个线程,同时访问某一个资源。
信号量主要提供了以下构造函数:
public Semaphore(int permits)
public Semaphore(int permits, boolean fair) // 第二个参数可以指定是否公平
在构造信号量对象时,必须要指定信号量作为准入数,即同时能申请多少个许可。当每个线程每次只申请一个许可时,就相当于指定了同时有多少个线程可以访问某一个资源。
信号量的主要方法:
public void acquire()
public void acquireUninterruptibly()
public boolean tryAcquire()
public boolean tryAcquire(long timeout, TimeUnit unit)
public void release()

acquire()方法尝试获得一个准入的许可。若无法获得,则线程会等待,直到有线程释放一个许可或者当前线程被中断。acquireUninterruptibly()方法与acquire()类似,但不响应中断。
tryAcquire()尝试获得一个许可,成功则返回true,失败则返回false,它不会等待,会立即返回。release()释放一个许可给其它线程。

示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemophoreDemo implements Runnable {

final Semaphore sema = new Semaphore(5);
@Override
public void run() {
    try {
		sema.acquire();
		//模拟耗时操作
		Thread.sleep(2000);
		System.out.println(Thread.currentThread().getId()+":done!");
		sema.release();
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}
public static void main(String[] args) {
	ExecutorService exec = Executors.newFixedThreadPool(20);
	final SemophoreDemo demo = new SemophoreDemo();
	for(int i=0; i<20; i++){
		exec.submit(demo);
	}
	exec.shutdown();
}

}

ReadWriteLock读写锁:
ReadWriteLock是JDK5中提供的读写分离锁,读写分离可以有效地帮助减少锁竞争,以提升系统新能。如果在系统中,读操作次数远远大于写操作,则读写锁可以很大程度上地提升性能。
示例代码:

package com.canww.test1;

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

public class ReadWriteLockDemo {

private static Lock lock = new ReentrantLock();   // 普通重入锁
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  // 读写分离锁
private static Lock readLock = readWriteLock.readLock();   // 读锁
private static Lock writeLock = readWriteLock.writeLock(); // 写锁
private int value;

public Object doRead(Lock lock) throws InterruptedException{
	try{
		lock.lock();          //模拟读操作
		Thread.sleep(1000);   //读操作耗时越多,读写锁的优势就越明显
		return value;
	}finally{
		lock.unlock();
	}
}

public void doWrite(Lock lock, int index) throws InterruptedException{
	try{
		lock.lock();           //模拟写操作
		Thread.sleep(1000);			
		value = index;
	}finally{
		lock.unlock();
	}
}

public static void main(String[] args) {
	final ReadWriteLockDemo demo = new ReadWriteLockDemo();
	
	Runnable read = new Runnable(){
		public void run() {
			try {
				demo.doRead(readLock);  //demo.doRead(lock);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	};
	
	Runnable write = new Runnable(){
		public void run() {
			try {
				demo.doWrite(writeLock, new Random().nextInt());  //  demo.doWrite(lock, new Random().nextInt());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	};
	
	for(int i=0; i<18; i++){
		new Thread(read).start();
	}
	
	for(int i=18; i<20; i++){
		new Thread(write).start();
	}
}

}

posted @ 2017-11-01 07:34  西风.烈马  阅读(187)  评论(0编辑  收藏  举报