鎖對象Lock-同步問題更完美的處理方式

Lockjava.util.concurrent.locks包下的接口,Lock 實現提供了比使用synchronized 方法和語句可得到的更普遍的鎖定操做,它能以更優雅的方式處理線程同步問題,固然也能實現sychronized同樣的效果,代碼以下:java

package org.thread;

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

public class Output {

	private Lock lock = new ReentrantLock();

	public void output(String name) {
		
		try {
			lock.lock();
			for (int i = 0; i < name.length(); i++) {
				System.out.print(name.charAt(i));

			}

		} catch (Exception e) {

		} finally {
			lock.unlock();
		}

	}

}

如今看看併發

package org.thread;

public class Outputer {
	
	public synchronized void input(String name){
		
					for(int i =0;i<name.length();i++){
				System.out.print(name.charAt(i));
		}
		
	}

}

這兩個方法其實都是爲了實現數據同步dom

package org.thread;

public class LockTest {
	
	public static void main(String[] args) {
		final Outputer outputer = new Outputer();
		final Output output = new Output();
		Runnable runnable1 = new Runnable() {
			public void run() {
				
				outputer.input("Heinrich");
			}
		};
		
		Runnable runnable2 = new Runnable() {
			
			@Override
			public void run() {
				outputer.input("AmiLoveMe");
			}
		};
		
		Runnable runnable3 = new Runnable() {
			public void run() {
				
				output.output("Heinrich");
			}
		};
		
		Runnable runnable4 = new Runnable() {
			
			@Override
			public void run() {
				output.output("AmiLoveMe");
			}
		};
		
		new Thread(runnable2).start();
		new Thread(runnable1).start();
		new Thread(runnable3).start();
		new Thread(runnable4).start();
		
	}

}

看看控制檯的信息是否是咱們想要的,結果確定是的,反正我以爲是ide

AmiLoveMeHeinrichHeinrichAmiLoveMe  是我要的結果,有序,數據一致

這樣就實現了和sychronized同樣的同步效果,須要注意的是,用sychronized修飾的方法或者語句塊在代碼執行完以後鎖自動釋放,而是用Lock須要咱們手動釋放鎖,因此爲了保證鎖最終被釋放(發生異常狀況),要把互斥區放在try內,釋放鎖放在finally內。性能

若是說這就是Lock,那麼它不能成爲同步問題更完美的處理方式,下面要介紹的是讀寫鎖(ReadWriteLock),咱們會有一種需求,在對數據進行讀寫的時候,爲了保證數據的一致性和完整性,須要讀和寫是互斥的,寫和寫是互斥的,可是讀和讀是不須要互斥的,這樣讀和讀不互斥性能更高些,來看一下不考慮互斥狀況的代碼原型:this

如今看代碼:沒有讀寫鎖的spa

package org.thread;

public class Data {
	
	private Integer data;

	public void get() {
		System.out.println(Thread.currentThread().getName()+"準備讀取數據");
		try {
			Thread.sleep(4000);
		} catch (Exception e) {
		}
		System.out.println(Thread.currentThread().getName()+"讀取"+this.data);
	}

	public void set(Integer data) {
		System.out.println(Thread.currentThread().getName()+"準備寫入數據");
		try {
			
			Thread.sleep(4000);
		} catch (Exception e) {
		}
		this.data = data;
		System.out.println(Thread.currentThread().getName()+"寫入"+this.data);
	}
	
	


}
package org.thread;

import java.util.Random;

public class DataThread {

	public static void main(String[] args) {
		final Data data = new Data();
		for (int i = 0; i < 10; i++) {

			Runnable runnable1 = new Runnable() {

				@Override
				public void run() {
					data.set(new Random().nextInt(100));

				}
			};

			new Thread(runnable1).start();
		}
		
		for (int i = 0; i < 10; i++) {

			Runnable runnable2 = new Runnable() {

				@Override
				public void run() {
					data.get();

				}
			};
			
			new Thread(runnable2).start();
		}
		

		

	}

}

看看控制檯線程

Thread-0準備寫入數據
Thread-8準備寫入數據
Thread-5準備寫入數據
Thread-4準備寫入數據
Thread-3準備寫入數據
Thread-2準備寫入數據
Thread-7準備寫入數據
Thread-1準備寫入數據
Thread-6準備寫入數據
Thread-9準備寫入數據
Thread-10準備讀取數據
Thread-12準備讀取數據
Thread-11準備讀取數據
Thread-14準備讀取數據
Thread-15準備讀取數據
Thread-16準備讀取數據
Thread-13準備讀取數據
Thread-17準備讀取數據
Thread-18準備讀取數據
Thread-19準備讀取數據
Thread-7寫入28
Thread-3寫入56
Thread-8寫入83
Thread-2寫入88
Thread-9寫入83
Thread-5寫入88
Thread-0寫入84
Thread-6寫入28
Thread-1寫入28
Thread-4寫入28
Thread-19讀取56
Thread-12讀取56
Thread-14讀取56
Thread-13讀取56
Thread-16讀取56
Thread-10讀取56
Thread-11讀取56
Thread-15讀取56
Thread-17讀取56
Thread-18讀取56

咱們要實現寫入和寫入互斥,讀取和寫入互斥,讀取和讀取互斥,在set和get方法加入code

synchronized修飾符接口

package org.thread;

public class Data {
	
	private Integer data;

	public synchronized void get() {
		System.out.println(Thread.currentThread().getName()+"準備讀取數據");
		try {
			Thread.sleep(4000);
		} catch (Exception e) {
		}
		System.out.println(Thread.currentThread().getName()+"讀取"+this.data);
	}

	public synchronized void set(Integer data) {
		System.out.println(Thread.currentThread().getName()+"準備寫入數據");
		try {
			
			Thread.sleep(4000);
		} catch (Exception e) {
		}
		this.data = data;
		System.out.println(Thread.currentThread().getName()+"寫入"+this.data);
	}
	
	


}
Thread-0準備寫入數據
Thread-0寫入54
Thread-19準備讀取數據
Thread-19讀取54
Thread-18準備讀取數據
Thread-18讀取54
Thread-17準備讀取數據
Thread-17讀取54
Thread-16準備讀取數據
Thread-16讀取54
Thread-15準備讀取數據
Thread-15讀取54
Thread-14準備讀取數據
Thread-14讀取54
Thread-13準備讀取數據
Thread-13讀取54
Thread-12準備讀取數據
Thread-12讀取54
Thread-11準備讀取數據
Thread-11讀取54
Thread-10準備讀取數據
Thread-10讀取54
Thread-9準備寫入數據
Thread-9寫入42
Thread-8準備寫入數據
Thread-8寫入86
Thread-1準備寫入數據
Thread-1寫入30
Thread-2準備寫入數據
Thread-2寫入3
Thread-4準備寫入數據
Thread-4寫入81
Thread-3準備寫入數據
Thread-3寫入72
Thread-5準備寫入數據
Thread-5寫入15
Thread-6準備寫入數據
Thread-6寫入16
Thread-7準備寫入數據
Thread-7寫入33

咱們發現,雖然寫入和寫入互斥了,讀取和寫入也互斥了,可是讀取和讀取之間也互斥了,不能併發執行,效率較低,用讀寫鎖實現代碼以下:

package org.thread;

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

public class DataSyn {

	private Integer data;
	private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

	public void get() {
		System.out.println(Thread.currentThread().getName() + "準備讀取數據");
		readWriteLock.readLock().lock();;
		try {
			Thread.sleep(2000);
			System.out.println(Thread.currentThread().getName() + "正在讀取數據"
					+ this.data);
		} catch (Exception e) {
		} finally {
			readWriteLock.readLock().unlock();

		}

	}

	public void set(Integer data) {
		System.out.println(Thread.currentThread().getName() + "準備寫入數據");
		readWriteLock.writeLock().lock();;
		try {
			this.data = data;
			System.out.println(Thread.currentThread().getName()+"正在寫入"+data);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			readWriteLock.writeLock().unlock();
		}

	}

}
Thread-5準備寫入數據
Thread-5正在寫入85
Thread-1準備寫入數據
Thread-1正在寫入74
Thread-6準備寫入數據
Thread-6正在寫入28
Thread-0準備寫入數據
Thread-0正在寫入93
Thread-3準備寫入數據
Thread-4準備寫入數據
Thread-7準備寫入數據
Thread-8準備寫入數據
Thread-3正在寫入75
Thread-2準備寫入數據
Thread-2正在寫入75
Thread-4正在寫入70
Thread-7正在寫入65
Thread-9準備寫入數據
Thread-8正在寫入92
Thread-9正在寫入88

這個是否是效率更好了,固然咯,要否則說這麼多幹什麼

相關文章
相關標籤/搜索