1. 程式人生 > >Java多執行緒同步的幾種方式

Java多執行緒同步的幾種方式

當多個執行緒同時訪問一個資源時,非常容易出現安全問題。因此需要採用同步機制來解決這種問題。java主要提供了3種實現同步機制的方法:

1)、synchronized關鍵字

synchronized有兩種用法(synchronized方法和synchronized塊)

synchronized方法。在方法的生命前加入synchronized關鍵字,示例如下:

public synchronized void mutithreadAccess();

synchronized塊:synchronized塊既可以把任意的程式碼宣告為synchronized,也可以指定上鎖的物件。有非常高的靈活性,程式碼如下:

synchronized(syncObject){程式碼塊}

2)、wait()方法和notify()方法:

當使用synchronized來修飾某個共享資源時,如果執行緒A1執行synchronized程式碼,另外一個執行緒A2也要同時執行同一物件的同一synchronized程式碼時,執行緒A2將要等到執行緒A1執行完後,才能繼續執行。這種情況下可以使用wait()方法和notify()方法。

在synchronized程式碼被執行期間,執行緒可以呼叫物件的wait方法,釋放物件鎖,進入等待狀態,並且可以呼叫notify()方法或notify()方法通知正在等待的其他執行緒。notify()方法僅喚醒一個執行緒(等待佇列中的第一個執行緒)並允許它去獲得鎖,notifyAll()方法喚醒所有等待這個物件的執行緒並允許它們去獲得鎖。

3)、Lock

JDK5新增了Lock介面以及它的一個實現類ReentrantLock(重入鎖),Lock也可以用來實現多執行緒同步。

import java.util.concurrent.locks.*;
class Resource
{
	private String name;
	private int count=1;
	private boolean flag=false;
	private Lock lock=new ReentrantLock();

	private Condition condition_pro=lock.newCondition();
	private Condition condition_con=lock.newCondition();
	public void set(String name)  throws InterruptedException
	{
		lock.lock();
		try
		{
			while(flag)
				condition_pro.await();
			this.name=name+"-----"+count++;
			System.out.println(Thread.currentThread().getName()+"------生產者-------"+this.name);
			flag=true;
			condition_con.signal();
		}
		finally
		{
			lock.unlock();
		}
	}
	public 	void out() throws InterruptedException
	{
		lock.lock();
		try
		{
			while(!flag)
				condition_con.await();
			System.out.println(Thread.currentThread().getName()+"--消費者--"+this.name);
			flag=false;
			condition_pro.signal();
		}
		finally
		{
		   	lock.unlock();
		}	
	}
}
class Producer implements Runnable
{
	private Resource res;
	Producer(Resource res)
	{
		this.res=res;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				res.set("++麵包++");
			}
			catch (InterruptedException e)
			{
			}
			
		}
	}
}
class Consumer implements Runnable
{
	private Resource res;
	Consumer(Resource res)
	{
		this.res=res;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				res.out();
			}
			catch (InterruptedException e)
			{
			}
		}
	}
}
class ProducerConsumerDemo2 
{
	public static void main(String[] args) 
	{
		Resource res=new Resource();
		
		Producer pro=new Producer(res);
		Consumer con=new Consumer(res);
		
		Thread t1=new Thread(pro);
		Thread t2=new Thread(pro);
		Thread t3=new Thread(con);
		Thread t4=new Thread(con);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}