讀寫者問題-java實現

yilip發表於2014-12-17
   讀者—寫者問題(Readers-Writers problem)也是一個經典的併發程式設計問題,是經常出現的一種同步問題。計算機系統中的資料(檔案、記錄)常被多個程式共享,但其中某些程式可能只要求讀資料(稱為讀者Reader);另一些程式則要求修改資料(稱為寫者Writer)。就共享資料而言,Reader和Writer是兩組併發程式共享一組資料區,要求:
(1)允許多個讀者同時執行讀操作;
(2)不允許讀者、寫者同時操作;

(3)不允許多個寫者同時操作。

實現的原理:

     單純使用訊號量不能解決讀者與寫者問題,必須引入計數器readcount對讀程式計數;readcountsemophore 是用於對計數器readcount 操作的互斥訊號量,之所以引入該訊號量是為了保證原子操作(其實java中有關鍵字synchronized可以實現對塊的原子操作,保證只有一個執行緒來操作該塊,其實這個關鍵字就是封裝了訊號量)。write表示是否允許寫的訊號量;於是讀者優先的程式設計原理如下:

讀者:

  while(true)

      P(rcs);

     if(rc==0)

    {

          rc++;

          P(write);

    }

   V(rcs);

//讀資料

  P(rcs)

   rc--;

    if(rc==0)

         V(write);

  V(rcs)

寫者:

while(true)

{

      P(write);

      //寫寫寫

      V(write);

}

java 實現:

          讀者:

import java.util.Random;
import java.util.concurrent.Semaphore;

public class ReadThread extends Thread
{
	public int id;// 讀者ID
	//public int readCount;// 讀者數量
	public Semaphore readCountSemaphore;// 讀者數量訊號量
	public Semaphore writeSemaphore;// 寫者訊號量

	public ReadThread(int id,  Semaphore semaphore,
			Semaphore semaphore2)
	{
		this.id = id;
		this.readCount = rcount;
		this.readCountSemaphore = semaphore;
		this.writeSemaphore=semaphore2;
		this.start();// 開始讀
	}
//讀者優先
	public void run()
	{
		try
		{
			//沒人在寫
			if(writeSemaphore.availablePermits()>0)//可以讀
				System.out.println("讀者"+id+"可以讀...");
			else {
				System.out.println("有寫者在寫操作,讀者"+id+"等待讀...");
			}
			// 等待著讀
			readCountSemaphore.acquire();
			if (<span style="font-family: Arial, Helvetica, sans-serif;">ReadAndWrite.</span>readCount == 0)//如果第一個讀者,那麼要考慮是否有寫者,沒有寫者,直接讀,有寫者,等待寫者
			{
                               //此時不能寫
				<span style="font-family: Arial, Helvetica, sans-serif;">ReadAndWrite.</span><span style="font-family: Arial, Helvetica, sans-serif;">readCount</span><span style="font-family: Arial, Helvetica, sans-serif;">++;// 已經具備讀的條件了,讀者數量加1</span>
				writeSemaphore.acquire();
			}
			readCountSemaphore.release();
			/**********************************/
			
			//此刻才可以允許其他讀者讀資料
			
			/**********************************/
			readCountSemaphore.acquire();
			//可以讀了
			System.out.println("讀者"+id+"我正在讀哦...");
			Thread.sleep((long) (new Random().nextFloat()*2000));
			System.out.println("讀者"+id+"讀完了...");
			//讀完了,讀者數量減少1
			ReadAndrWrite.readCount--;
			if(<span style="font-family: Arial, Helvetica, sans-serif;">ReadAndrWrite.</span><span style="font-family: Arial, Helvetica, sans-serif;">readCount==0)//沒有讀者了,可以寫了</span>
			{
				writeSemaphore.release();
			}
			readCountSemaphore.release();//釋放讀者訊號量
			
		}
		catch (InterruptedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

寫者:

import java.util.Random;
import java.util.concurrent.Semaphore;

public class WriteThread extends Thread
{
   public int id;//編號
   public Semaphore writeSemaphore;//寫者訊號量
   public WriteThread(int id,Semaphore semaphore)
   {
	   this.id=id;
	   this.writeSemaphore=semaphore;
	   this.start();
   }
   public void run()
   {
	   try
	{
		 if(writeSemaphore.availablePermits()>0)
		 {
			 System.out.println("寫者"+this.id+"可以寫");
		 }
		 else
			 System.out.println("寫者"+this.id+"不可以寫");		 
		writeSemaphore.acquire();
		System.out.println("寫者"+this.id+"正在寫...");
		Thread.sleep((long) (new Random().nextFloat()*2000));
		System.out.println("寫者"+this.id+"寫完了...");
		writeSemaphore.release();
	}
	catch (InterruptedException e)
	{
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   }
}

主程式:

public class ReadAndWrite
{
	public static final int count=10;//讀者寫者的數量
	public static 	int readCount=0;

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Semaphore readCountSemaphore=new Semaphore(1);
		Semaphore writeSemaphore=new Semaphore(1);
        for(int i=0;i<count;i++)
        {
        	//隨機生成讀者和寫者
        	if(new Random().nextBoolean())//假設是讀者
        		new ReadThread(i, readCountSemaphore, writeSemaphore);
        	else {
				new WriteThread(i, writeSemaphore);
			}
        }
	}

}



執行效果:

 

      

相關文章