Java多線程知識點整理(Lock鎖)

1.Lock的使用java

private Lock lock = new ReentrantLock();

public void test(){
   lock.lock();

   System.out.println("#######");
     
   lock.unlock();

}

注意:try-catch-finally結合使用,unlock()在finally裏面。ide

2.使用condition實現等待/通知spa

    關鍵字synchronized與wait()和notify()/notifyAll()方法相結合能夠實現等待/通知模式,類ReentrantLock也能夠實現一樣的功能,但須要藉助Condition對象。能夠實現多路通知功能,也就是在一個Lock對象裏面能夠建立多個Condition實例,線程對象能夠註冊在指定Condition中,從而能夠有選擇性進行線程通知,在調度線程上更加靈活。線程

    synchronized的wait()和notify(),而Condition對象,卻能夠選擇性通知。code

2.1 使用condition API對象

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class test5 {
	
	private Lock lock = new  ReentrantLock();
	
	public Condition condition1 = lock.newCondition();
	
	public Condition condition2 = lock.newCondition();
	
	public void awaitA(){
		try {
			lock.lock();
			System.out.println("A等待");
			condition1.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
		
	}
	public void awaitB(){
		try {
			lock.lock();
			System.out.println("B等待");
			condition2.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
	public void signalA(){
		try {
			lock.lock();
			System.out.println("通知a");
			condition1.signalAll();
		} finally {
			lock.unlock();
		}
			// TODO: handle finally clause
		}
	public void signalB(){
		try {
			lock.lock();
			System.out.println("通知B");
			condition2.signalAll();
		} finally {
			lock.unlock();
		}
			// TODO: handle finally clause
		}
	
	public static void main(String[] args) {
		
		test5 t5 = new test5();
		//建立兩個線程
		// Thread thread1= new Thread(t5);
		//Thread thread2= new Thread(t5);
		//只通知線程1
		//
		t5.signalA();
	}
}

2.二、生產者與消費模式:交替打印get

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class test6 {
	private Lock lock =new ReentrantLock();
	
	private Condition condition=  lock.newCondition();
	
	private boolean hasValue= false;
	public void set(){
		try {
		lock.lock();
		while(hasValue == true){
			condition.await();
		}
		System.out.println("@@@");
		hasValue= true;
		condition.signal();
		
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			lock.unlock();
		}
	}
	
	public void get(){
		try {
			lock.lock();
			while(hasValue == false){
				condition.await();
			}
			System.out.println("###");
			hasValue= false;
			condition.signal();
			
			} catch (Exception e) {
				// TODO: handle exception
			}finally {
				lock.unlock();
			}
	}
	public static void main(String[] args) {
		test6 test6 = new test6();
		//建立兩個線程
		//啓動
	}
}

注意:多消費者和多生產者,使用condition.signalAll();it

3.公平鎖與非公平鎖io

    鎖Lock分爲「公平鎖」和「非公平鎖」,公平鎖表示線程獲取的順序是按照線程加鎖的順序來分配的,即先來得的FIFO先進先出的順序。而非公平鎖就是一種獲取搶佔機制,是隨機得到鎖的,和公平鎖不同就是先來得不必定先獲得鎖,這個方式可能形成某些線程一直拿不到鎖,結果也就是不公平的了。class

import java.util.concurrent.locks.ReentrantLock;

public class test7 {
	private ReentrantLock lock;
	public test7(boolean isFair){//傳入true表示公平鎖,反之爲非公平鎖
		super();
		lock = new ReentrantLock();
	}
	public void add(){
		try {
			lock.lock();
			
		} finally {
			lock.unlock();
		}
		
	}
}

4.API講解

4.一、方法lockInterruptibly()

    該方法的做用是:若是當前線程未被中斷,則獲取鎖定,若是已經被中斷則拋出異常。

4.二、tryLock()

    改方法的做用是:僅在調用時鎖定未被另外一個線程保持的狀況下,才獲取該鎖。

private Lock lock = new ReentrantLock();

public void test(){
   if(lock.tryLock()){
      System.out.println("#######");

   }

}

    同時,tryLock(long timeout,TimeUnit unit)的做用是,若是鎖定在給等待時間內沒有被另外一個線程保持,且當前線程未被中斷,則獲取該鎖定。

4.三、使用Condition實現順序執行

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class test8 {
	volatile private static int nextPrintWho =1;
	private static ReentrantLock lock = new ReentrantLock();
	final private static Condition conditionA = lock.newCondition();
	final private static Condition conditionB = lock.newCondition();
	final private static Condition conditionC = lock.newCondition();
	public static void main(String[] args) {
		Thread threadA = new Thread(){
			@Override
			public void run() {
				try {
					lock.lock();
					while(nextPrintWho != 1){
						conditionA.await();
					}
					for(int i=1; i<4;i++){
						System.out.println("ThreadA"+i);
					}
					nextPrintWho = 2;
					conditionB.signalAll();
				} catch (Exception e) {
					// TODO: handle exception
				}finally {
					lock.unlock();
				}
			}
		};
		Thread threadB = new Thread(){
			@Override
			public void run() {
				try {
					lock.lock();
					while(nextPrintWho != 2){
						conditionB.await();
					}
					for(int i=1; i<4;i++){
						System.out.println("ThreadB"+i);
					}
					nextPrintWho = 3;
					conditionC.signalAll();
				} catch (Exception e) {
					// TODO: handle exception
				}finally {
					lock.unlock();
				}
			}
		};
		Thread threadC = new Thread(){
			@Override
			public void run() {
				try {
					lock.lock();
					while(nextPrintWho != 3){
						conditionC.await();
					}
					for(int i=1; i<4;i++){
						System.out.println("ThreadC"+i);
					}
					nextPrintWho = 1;
					conditionA.signalAll();
				} catch (Exception e) {
					// TODO: handle exception
				}finally {
					lock.unlock();
				}
			}
		};
		Thread[] aAray =new Thread[5];
		Thread[] bAray =new Thread[5];
		Thread[] cAray =new Thread[5];
		for(int i=0;i<5;i++){
			aAray[i] =new Thread(threadA);
			 bAray[i] =new Thread(threadB);
			 cAray[i] =new Thread(threadC);
			 aAray[i].start();
			 bAray[i].start();
					 cAray[i].start();
		}
		
	}
}

總結:實現線程的順序執行,可使用:join方法,也可使用Condition。

5.使用ReentrantReadWriteLock類

    讀寫鎖表示有兩個鎖,一個是讀操做相關的鎖,也稱爲共享鎖;另外一個是寫操做相關的的鎖,也叫排它鎖。也就是多個讀鎖之間不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥。在沒有線程進行寫入操做時,進行讀取操做的多個線程均可以獲取鎖,而進行寫入的操做的線程只有在獲取寫鎖後才能進行操做。即多個線程能夠同時進行讀取操做,可是同一時刻只容許一個線程進行寫入操做。

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class test9 {
	
	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	public void read(){
		try {
			lock.readLock();
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			lock.readLock().unlock();
		}
	}
	
	public void wirte(){
		try {
			lock.writeLock();
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			lock.writeLock().unlock();
		}
	}
}
相關文章
相關標籤/搜索